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
会涉及字符编码问题 。 你实际上也不需要在这里了解它们。 所以就把它放在一边。
为了进一步提高性能,您始终可以将InputStream
和OutputStream
分别包装在BufferedInputStream
和BufferedOutputStream
。
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(); }