Java文件未使用新行字符写入流

我们正在从Web服务流式传输CSV文件。 看起来我们在流式传输时丢失了新的行字符 – 客户端将文件全部放在一行上。 知道我们做错了什么吗?

码:

public static void writeFile(OutputStream out, File file) throws IOException { BufferedReader input = new BufferedReader(new FileReader(file)); //File input stream String line; while ((line = input.readLine()) != null) { //Read file out.write(line.getBytes()); //Write to output stream out.flush(); } input.close(); } 

不要使用BufferedReader 。 你已经手头有一个OutputStream ,所以只需获取文件的InputStream并从输入中输出字节,然后以通常的Java IO方式输出它。 这样您也不必担心BufferedReader会吃掉换行符:

 public static void writeFile(OutputStream output, File file) throws IOException { InputStream input = null; byte[] buffer = new byte[10240]; // 10KB. try { input = new FileInputStream(file); for (int length = 0; (length = input.read(buffer)) > 0;) { output.write(buffer, 0, length); } } finally { if (input != null) try { input.close(); } catch (IOException logOrIgnore) {} } } 

如果您事先不知道/指定编码,则使用Reader / Writer会涉及字符编码问题 。 你实际上也不需要在这里了解它们。 所以就把它放在一边。

为了进一步提高性能,您始终可以将InputStreamOutputStream分别包装在BufferedInputStreamBufferedOutputStream

readline方法使用换行符来分隔读取的内容,因此readLine不会返回换行符本身。

不要使用readline,如果需要,可以使用BufferedInputStream并一次读取一个字节的文件,或者将自己的缓冲区传递给OutputStream.write。

请注意,就像BalusC和Michael Borgwardt所说,Readers和Writers是用于文本的,如果你只想复制文件,你应该使用InputStream和OutputStream,你只关心字节。

该代码有几个问题。 它也可能会破坏任何非ASCII文本,因为它通过平台默认编码转换两次 – 并且完全没有理由。

不要使用Reader来读取文件,使用FileInputStream并传输字节,从而避免不必要且可能具有破坏性的字符集转换。 换行问题也将消失。

知道我们做错了什么吗?

是。 此行删除了“新行字符”

 while ((line = input.readLine()) != null) { 

然后你没有它写它:

  out.write(line.getBytes()); 

这个相关的问题 。

BufferedReader.ReadLine()不保留换行符。 因此,在写出来时你必须添加它

您还可以使用New IO API( java.nio.* ):

 private static void copy(File source, File destination) throws IOException { long length = source.length(); FileChannel input = new FileInputStream(source).getChannel(); try { FileChannel output = new FileOutputStream(destination).getChannel(); try { for (long position = 0; position < length; ) { position += input.transferTo(position, length-position, output); } } finally { output.close(); } } finally { input.close(); } } 

可能不需要循环,但Channel.trasnferTo()的文档说

可能会也可能不会传输所有请求的字节

您可以使用提供prinln()方法的PrintWriter。 这也可以避免将字符串转换为字符数组。

 public static void writeFile(OutputStream o, File file) throws IOException { PrintWriter out = new PrintWriter(new OutputStreamWriter(o)); BufferedReader input = new BufferedReader(new FileReader(file)); //File input stream String line; while ((line = input.readLine()) != null) { //Read file out.println(line); //Write to output stream out.flush(); } input.close(); }