Есть ли способ сделать вывод PrintWriter в формате UNIX? - PullRequest
6 голосов
/ 18 июня 2009

На Яве, конечно. Я пишу программу и запускаю ее в среде Windows, но мне нужен вывод (.csv) в формате Unix. Любое простое решение? Спасибо!

Ответы [ 5 ]

13 голосов
/ 18 июня 2009

Примечание: как указано в комментариях, приведенный ниже подход нарушает JDK 9+. Используйте подход в ответе Джеймса Х.


Под "форматом Unix" вы подразумеваете использование "\ n" в качестве ограничителя строки вместо "\ r \ n"? Просто установите системное свойство line.separator перед созданием PrintWriter.

Так же, как демо:

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, что не идеально, но это может быть все, что вам может понадобиться.

12 голосов
/ 07 февраля 2013

Чтобы записать файл с окончаниями строки Unix, переопределите println в классе, производном от PrintWriter, и используйте print с \ 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, которые есть в вашем коде.

3 голосов
/ 18 июня 2009

При условии, что проблема форматирования, о которой вы говорите, заключается в том, что разрывы строк в Windows - это перевод строки с возвратом каретки ("\r\n"), а в Unix - только перевод строки ("\n"), самый простой способ убедиться, что ваш файл использует LF и не CRLF означает избегать println и вместо этого использовать print("\n") для завершения строк.

Так что вместо:

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

использование

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

Вы можете просто найти соответствующие файлы для println, чтобы убедиться, что вы поймали их всех.

2 голосов
/ 13 октября 2011

Программист-параноик будет синхронизироваться с объектом системных свойств, по крайней мере, если разным принтерам нужны разные типы ограничителей строки.

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);
            }
        }
    }
}
1 голос
/ 04 мая 2016

Я вижу еще 2 варианта, которые не влияют на всю систему или не приводят к проблемам параллелизма, таким как установка lineSeparator. Я также объявил бы enum, представляющий окончания строки.

 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 на другой, и, следовательно, вы должны использовать другую стратегию отражения.

  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();
        }
      }
    }
    
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...