有没有办法让PrintWriter输出为UNIX格式?

时间:2009-06-18 18:08:30

标签: java unix

当然是在Java中。我正在编写一个程序并在Windows环境下运行它,但我需要输出(.csv)以Unix格式完成。任何简单的方案?谢谢!

5 个答案:

答案 0 :(得分:13)

注意:正如评论中所述,下面给出的方法在JDK 9+中有所突破。在James H.的回答中使用这种方法。


“Unix格式”是指使用“\ n”作为行终止符而不是“\ r \ n”?只需在创建PrintWriter之前设置line.separator系统属性。

就像演示一样:

import java.io.*;

public class Test
{
    public static void main(String[] args)
        throws Exception // Just for simplicity
    {
        System.setProperty("line.separator", "xxx");
        PrintWriter pw = new PrintWriter(System.out);
        pw.println("foo");
        pw.println("bar");
        pw.flush();
    }
}

当然,它为整个JVM设置了它,这不是理想的,但它可能就是您所需要的一切。

答案 1 :(得分:12)

要编写带有unix行结尾的文件,请在从PrintWriter派生的类中覆盖println,并使用带\ n的打印。

PrintWriter out = new PrintWriter("testFile") {
    @Override
    public void println() {
        write('\n');
    }
};
out.println("This file will always have unix line endings");
out.println(41);
out.close();

这样可以避免触及代码中现有的任何println调用。

答案 2 :(得分:3)

假设您引用的格式问题是Windows换行符是回车换行符("\r\n"),而Unix换行符只是换行符("\n"),这是确保您的最简单方法文件使用LF而不是CRLF是避开println而是使用print("\n")来终止行。

所以而不是:

writer.println("foo,bar,88");

使用

writer.print("foo,bar,88\n");

您只需搜索println的相关文件,以确保全部捕获它们。

答案 3 :(得分:2)

一个偏执的程序员会在系统属性对象上进行同步,至少如果不同的Printwriters需要不同类型的行终止符。

public static PrintWriter createPrintWriter(OutputStreamWriter out, boolean autoflush){
    Properties props = System.getProperties();
    synchronized (props) {
        Object old = null;
        try {
        old = props.setProperty("line.separator", "\n");
        return  new PrintWriter(out, autoflush);
        } finally {
            if( old != null ) {
                props.put("line.separator", old);
            }
        }
    }
}

答案 4 :(得分:1)

我看到另外两个选项不会影响整个系统或导致并发问题,比如设置lineSeparator。我还会声明一个代表行结尾的枚举。

 enum LineEnding {
  UNIX("\n"), DOS("\r\n");

  private String lineSeparator;

  LineEnding(String lineSeparator) {
    this.lineSeparator = lineSeparator;
  }

  public String getLineSeparator() {
    return lineSeparator;
  }
}
  1. 使用反射设置lineSeperator

    您应该创建一个使用封装访问权限的工厂 反射从客户端隐藏PrintWriter内部。例如。客户端代码应如下所示:

    PrintWriterFactory.newPrintWriter(someWriter, LineEnding.UNIX);
    

    虽然实施可能如下所示:

    public class PrintWriterFactory {
    
      private static final Field lineSeparatorField;
    
      static {
        try {
          lineSeparatorField = PrintWriter.class.getDeclaredField("lineSeparator");
          lineSeparatorField.setAccessible(true);
        } catch (NoSuchFieldException e) {
          throw new IllegalStateException("java.io.PrintWriter implementation changed. Unable to determine lineSeparator field.", e);
        }
      }
    
      public static PrintWriter newPrintWriter(Writer writer, LineEnding lineEnding) {
        PrintWriter printWriter = new PrintWriter(writer);
    
        try {
          lineSeparatorField.set(printWriter, lineEnding.getLineSeparator());
        } catch (IllegalAccessException e) {
          throw new IllegalStateException("Can't set line ending", e);
        }
    
        return printWriter;
      }
    }
    

    PS:工厂不能是静态的。如果PrintWriter实现从一个JDK更改为另一个JDK,则可以使用接口和多个实现,因此必须使用其他反射策略。

  2. 扩展PrintWriter并覆盖println()方法

    public class LineEndingPrintWriter extends PrintWriter {
    
      protected boolean autoFlush = false;
      private LineEnding lineEnding;
    
      public LineEndingPrintWriter(Writer out, LineEnding lineEnding) {
        this(out, false, lineEnding);
      }
    
      public LineEndingPrintWriter(Writer out, boolean autoFlush, LineEnding lineEnding) {
        super(out, autoFlush);
        this.autoFlush = autoFlush;
        this.lineEnding = lineEnding;
      }
    
      public LineEndingPrintWriter(OutputStream out, LineEnding lineEnding) {
        this(out, false, lineEnding);
      }
    
      public LineEndingPrintWriter(OutputStream out, boolean autoFlush, LineEnding lineEnding) {
        super(out, autoFlush);
        this.autoFlush = autoFlush;
        this.lineEnding = lineEnding;
      }
    
      protected void ensureOpen() throws IOException {
        if (out == null)
          throw new IOException("Stream closed");
      }
    
      public void println() {
        // Method body taken from java.io.PrintWriter.println();
        try {
          synchronized (lock) {
            ensureOpen();
    
            out.write(lineEnding.getLineSeparator());
    
            if (autoFlush) {
              out.flush();
            }
          }
        } catch (InterruptedIOException e) {
          Thread.currentThread().interrupt();
        } catch (IOException e) {
          setError();
        }
      }
    }