当然是在Java中。我正在编写一个程序并在Windows环境下运行它,但我需要输出(.csv)以Unix格式完成。任何简单的方案?谢谢!
答案 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;
}
}
使用反射设置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,则可以使用接口和多个实现,因此必须使用其他反射策略。
扩展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();
}
}
}