资讯专栏INFORMATION COLUMN

关于java用字节流和字符流读取文件的各种情况

tommego / 968人阅读

摘要:遇到的问题在用通信传输一个文件以及其他的非文件的时候总是传到服务端的文件出错,后来发现是在用字符流和字节流在读取各种文件上的差别所导致的读取文件的方式字节流读取和,其读取的方式按字节读取,这个常用于读取原始数据。

遇到的问题

在用socket通信传输一个pdf文件以及其他的非txt文件的时候总是传到服务端的文件出错,后来发现是在用字符流和字节流在读取各种文件上的差别所导致的

java读取文件的方式

字节流读取:InputStream和OutPutStream,其读取的方式按字节读取,这个常用于读取原始数据。

字符流读取:Reader和Writer,按字节读取数据,java里面一个字符对应两个字节

为什么会有时候会出现乱码

在计算机中常会涉及到编码问题,那么在字符流读取文件的时候也会遇到一些问题,典型的就是在读取txt文件的时候再保存遇到的乱码,在java里面一个字符对应两个字节,但是在UTF-8的编码中有时候一个汉字可能对应的是三个字节,那么这个时候在读取的时候不指定编码的话会造成读取文件的乱码现象

一个txt文件假设是GBK编码的话,在以字符流读取的时候若依GBK读取就会造成问题

测试(JDK1.8,IDEA,默认编码UTF-8,txt文件编码GBK)
测试一

写了一个代码测试了下:
在以字节流去读取pdf格式和其他格式的文件都没问题,但是字节流读取之后保存为String再写入文件会导致pdf等文件出错:代码如下
此时会导致pdf文件全部是白的,音乐等文件全部错误,而且txt格式的文件的文字全部变成拷斤棍,至于拷斤棍百度了下是由于字符编码问题,

 File file1 =new File("D:disk1README.doc");
        File file2 =new File("D:disk	es.doc");
        Reader reader =new InputStreamReader(new FileInputStream(file1));
        int len;
        char[] a =new char[1024];
        StringBuffer sb =new StringBuffer();
        while ((len=reader.read(a))!= -1)  //以字节流去读pdf文件
        {
            sb.append(new String(a,0,len));
        }
        reader.close();
        FileWriter fileWriter = new FileWriter(file2); // 将读取出来的额String数据直接写入
        fileWriter.write(sb.toString());
        fileWriter.flush();
        fileWriter.close();
测试二

将读取之后的String再次变为字节流然后再进行读取再直接以字节流写入:
此时如同前面一个代码结果一样,除了txt有编码问题之外的文件都有问题

//        File  file1= new File("D:disk1Java锁.pdf");
//        File file2 =new File("D:disk	est1.pdf");
//        File file1 =new File("D:disk1Java锁.txt");
//        File file2 =new File("D:disk	est1.txt");
//        File file1 =new File("D:disk1Unit.wma");
//        File file2 =new File("D:disk	est1.wma");
        File file1 =new File("D:disk1README.doc");
        File file2 =new File("D:disk	est1.doc");
        InputStream in =null;
        OutputStream out =null;
        try{
            in= new FileInputStream(file1);
            byte[] bytes= new byte[1024];
            int read =0;
            StringBuffer sb =new StringBuffer();
            while ((read =in.read(bytes))!= -1)
            {
                sb.append(new String(bytes,0,read));
            }
            System.out.println("a");
            InputStream inputStream =new ByteArrayInputStream(sb.toString().getBytes());
            byte[] re =new byte[1024];
            int haveRead= 0;
            FileOutputStream fileOutputStream =new FileOutputStream(file2);
            while ((haveRead =inputStream.read(re))!= -1)
            {
                fileOutputStream.write(re,0,haveRead);
            }
            } catch (FileNotFoundException e1) {
            e1.printStackTrace();
        } catch (IOException e1) {
            e1.printStackTrace();
        }finally {
            in.close();
        }

    }
测试三:

全部以GBK格式读取和以GBK格式写入,除了txt文件正常以外其他的文件全部出错

 File file1 =new File("D:disk1Java锁.txt");
//        File file2 =new File("D:disk	est4.txt");
//        File file1 =new File("D:disk1Unit.wma");
//        File file2 =new File("D:disk	est4.wma");
        File file1 =new File("D:disk1README.doc");
        File file2 =new File("D:disk	est4.doc"); //拷斤棍
        FileInputStream fileInputStream =new FileInputStream(file1);
        Reader reader =new InputStreamReader(fileInputStream,"GBK"); // txt测试GBK结果正确 DOC测试以UTF-8测试结果:拷斤棍 //
        char[] chars =new char[1024];
        int read=0;
        StringBuffer sb =new StringBuffer();
        while((read=reader.read(chars))!= -1)
        {
            sb.append(new String(chars,0,read));
        }
        FileOutputStream fileOutputStream =new FileOutputStream(file2);
        Writer writer =new OutputStreamWriter(fileOutputStream,"GBK");
        writer.write(sb.toString());
        writer.flush();
        writer.close();

所以在java里面对文件的读写最好以字节流写入:此时无论是各种文件都没问题,对于字符流的使用感觉是在一些需要编码的文件,即类似于txt的文本文件。

 File file1 =new File("D:disk1Java锁.pdf");
//        File file2 =new File("D:diskcopy.pdf");
//        File file1 =new File("D:disk1Java锁.txt");
//        File file2 =new File("D:diskcopy.txt");
//        File file1 =new File("D:disk1Unit.wma");
//        File file2 =new File("D:diskcopy.wma");
        File file1 =new File("D:disk1README.doc");
        File file2 =new File("D:diskcopy.doc");
        InputStream in =null;
        OutputStream out =null;
        try{
            in= new FileInputStream(file1);
            out=new FileOutputStream(file2);
            byte[] bytes= new byte[1024];
            int read =0;
            StringBuffer sb =new StringBuffer();
            while ((read =in.read(bytes))!= -1)
            {
                out.write(bytes,0,read);    // 直接以字节流的方式输出到文件
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            in.close();
            out.close();
        }

全部代码

import java.io.*;

/**
 * Created by szh on 2017/3/26.
 */
public class FileTest {
    /*
    文件以字节流读取
    1.以这种方式读取非文档的
     */
    public static void tes() throws IOException {
//        File file1 =new File("D:disk1Java锁.pdf");
//        File file2 =new File("D:disk	es.pdf");
//        File file1 =new File("D:disk1Java锁.txt");
//        File file2 =new File("D:disk	es.txt");
//        File file1 =new File("D:disk1Unit.wma");
//        File file2 =new File("D:disk	es.wma");
        File file1 =new File("D:disk1README.doc");
        File file2 =new File("D:disk	es.doc");
        Reader reader =new InputStreamReader(new FileInputStream(file1));
        int len;
        char[] a =new char[1024];
        StringBuffer sb =new StringBuffer();
        while ((len=reader.read(a))!= -1)  //以字节流去读pdf文件
        {
            sb.append(new String(a,0,len));
        }
        reader.close();
        FileWriter fileWriter = new FileWriter(file2); // 将读取出来的额String数据直接写入
        fileWriter.write(sb.toString());
        fileWriter.flush();
        fileWriter.close();
    }
    /*
    以字节流来读取文件
     */
    public static void test2() throws IOException {
//        File file1 =new File("D:disk1Java锁.pdf");
//        File file2 =new File("D:disk	est2.pdf");
//        File file1 =new File("D:disk1Java锁.txt");
//        File file2 =new File("D:disk	est2.txt");
//        File file1 =new File("D:disk1Unit.wma");
//        File file2 =new File("D:disk	est2.wma");
        File file1 =new File("D:disk1README.doc");
        File file2 =new File("D:disk	est2.doc");
        byte[] sendBytes = new byte[1024];
        int length = 0;
        StringBuffer sb =new StringBuffer();
        FileInputStream fileInputStream =new FileInputStream(file1);
        while((length = fileInputStream.read(sendBytes, 0, sendBytes.length)) > 0){  // 将文件读取为String
            sb.append(new String(sendBytes, 0, length));
        }
        FileWriter fileWriter = new FileWriter(file2);     // 这里会导致读取出来的txt文字都是拷斤棍
        fileWriter.write(sb.toString());
        fileWriter.flush();
        fileWriter.close();
    }
    /*
    以字节流读取但是不读取为String
     */
    public  static  void copy() throws IOException {
//        File file1 =new File("D:disk1Java锁.pdf");
//        File file2 =new File("D:diskcopy.pdf");
//        File file1 =new File("D:disk1Java锁.txt");
//        File file2 =new File("D:diskcopy.txt");
//        File file1 =new File("D:disk1Unit.wma");
//        File file2 =new File("D:diskcopy.wma");
        File file1 =new File("D:disk1README.doc");
        File file2 =new File("D:diskcopy.doc");
        InputStream in =null;
        OutputStream out =null;
        try{
            in= new FileInputStream(file1);
            out=new FileOutputStream(file2);
            byte[] bytes= new byte[1024];
            int read =0;
            StringBuffer sb =new StringBuffer();
            while ((read =in.read(bytes))!= -1)
            {
                out.write(bytes,0,read);    // 直接以字节流的方式输出到文件
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            in.close();
            out.close();
        }
    }
    /*
    将文件以字节流的方式读取文件转为String但是又重新将String转为字节流然后写入
     */
    public static void test1() throws IOException {
//        File  file1= new File("D:disk1Java锁.pdf");
//        File file2 =new File("D:disk	est1.pdf");
//        File file1 =new File("D:disk1Java锁.txt");
//        File file2 =new File("D:disk	est1.txt");
//        File file1 =new File("D:disk1Unit.wma");
//        File file2 =new File("D:disk	est1.wma");
        File file1 =new File("D:disk1README.doc");
        File file2 =new File("D:disk	est1.doc");
        InputStream in =null;
        OutputStream out =null;
        try{
            in= new FileInputStream(file1);
            byte[] bytes= new byte[1024];
            int read =0;
            StringBuffer sb =new StringBuffer();
            while ((read =in.read(bytes))!= -1)
            {
                sb.append(new String(bytes,0,read));
//                out.write(bytes,0,read);
                System.out.println(read+"-----------read的值");
            }
            System.out.println("a");
            InputStream inputStream =new ByteArrayInputStream(sb.toString().getBytes());
            byte[] re =new byte[1024];
            int haveRead= 0;
            FileOutputStream fileOutputStream =new FileOutputStream(file2);
            while ((haveRead =inputStream.read(re))!= -1)
            {
                fileOutputStream.write(re,0,haveRead);
            }
            } catch (FileNotFoundException e1) {
            e1.printStackTrace();
        } catch (IOException e1) {
            e1.printStackTrace();
        }finally {
            in.close();
        }

    }
    /*
    修改编码
     */
    public static void test3() {
//        File file1 =new File("D:disk1Java锁.pdf");
//        File file2 =new File("D:diskcopy.pdf");
//        File file1 = new File("D:disk1Java锁.txt");
//        File file2 = new File("D:disk	est3.txt");
//        File file1 =new File("D:disk1Unit.wma");
//        File file2 =new File("D:disk	est3.wma");
        File file1 =new File("D:disk1README.doc");
        File file2 =new File("D:disk	est3.doc");
        InputStream in = null;
        OutputStream out = null;
        try {
            in = new FileInputStream(file1);
            out = new FileOutputStream(file2);
            byte[] bytes = new byte[1024];
            int read = 0;
            StringBuffer sb = new StringBuffer();
            while ((read = in.read(bytes)) != -1) {
                sb.append(new String(bytes, 0, read));
            }
            InputStream inputStream = new ByteArrayInputStream(sb.toString().getBytes());
            byte[] re = new byte[1024];
            int haveRead = 0;
            FileOutputStream fileOutputStream = new FileOutputStream(file2);
            StringBuffer sb2 = new StringBuffer();
            while ((haveRead = inputStream.read(re)) != -1) {
//                fileOutputStream.write(re,0,haveRead);
                sb2.append(new String(re, 0, haveRead));
            }
            OutputStreamWriter outputStreamWriter = new OutputStreamWriter(fileOutputStream, "GBK");  // 在这里转换的话会导致都是?
            outputStreamWriter.write(sb2.toString());
            outputStreamWriter.close();
        } catch (FileNotFoundException e1) {
            e1.printStackTrace();
        } catch (IOException e1) {
            e1.printStackTrace();
        } finally {
        }
    }

    public static void test4() throws IOException {
//        File file1 =new File("D:disk1Java锁.txt");
//        File file2 =new File("D:disk	est4.txt");
//        File file1 =new File("D:disk1Unit.wma");
//        File file2 =new File("D:disk	est4.wma");
        File file1 =new File("D:disk1README.doc");
        File file2 =new File("D:disk	est4.doc"); //拷斤棍
        FileInputStream fileInputStream =new FileInputStream(file1);
        Reader reader =new InputStreamReader(fileInputStream,"UTF-8"); // txt测试GBK结果正确 DOC测试以UTF-8测试结果:拷斤棍 //
        char[] chars =new char[1024];
        int read=0;
        StringBuffer sb =new StringBuffer();
        while((read=reader.read(chars))!= -1)
        {
            sb.append(new String(chars,0,read));
        }
        FileOutputStream fileOutputStream =new FileOutputStream(file2);
        Writer writer =new OutputStreamWriter(fileOutputStream,"UTF-8");
        writer.write(sb.toString());
        writer.flush();
        writer.close();
    }


    public static void main(String args[]) throws IOException {
        tes();
        test2();
        copy();
        test1();
        test3();
        test4();
    }


}

项目地址:https://github.com/Somersames...

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/66904.html

相关文章

  • 高薪程序员&面试题精讲系列22之说说JavaIO,常用哪些IO

    摘要:一面试题及剖析今日面试题今天壹哥带各位复习一块可能会令初学者比较头疼的内容,起码当时让我很有些头疼的内容,那就是流。在这里壹哥会从两部分展开介绍流,即与流。除此之外尽量使用字节流。关闭此输入流并释放与流相关联的任何系统资源。 一. 面试题及剖析 1. 今日面试题 今天 壹哥 带各位复习一块可...

    fnngj 评论0 收藏0
  • 第十一章-IO#yyds干货盘点#

    摘要:是一个系统支持的所有字符的集合,包括各国家文字标点符号图形符号数字等字符集简体中文码表。支持中国国内少数民族的文字,同时支持繁体汉字以及日韩汉字等字符集为表达任意语言的任意字符而设计,是业界的一种标准,也称为统一码标准万国码。 1 File1.1 File类的概述和构造方法File: 它是文件和目录路径名的抽象...

    不知名网友 评论0 收藏0
  • 第十五章 输入输出系统

    摘要:在包下主要包括输入输出两种流,每种输入输出流又可分为字节流和字符流两大类。输入输出是从程序运行所在的内存的角度而言的。的输入流主要由和作为基类,而输出流主要由和作为基类。 本章主要参考和摘自疯狂java讲义上面的(java编程思想的后面看过后有新的内容再补充进去吧)。  输入输出是所有程序都必需的部分————使用输入机制允许程序读取外部数据(包括磁盘、光盘等存储设备上的数据和用户输入的...

    hankkin 评论0 收藏0
  • JavaIO之输出|乐字节

    摘要:大家好,乐字节小乐又来了。上一篇给大家带来的是中的流之输入流乐字节,本文将继续讲述流之输出流。一输出流抽象类和和也非常相似。从上述的字节数组中,读取字符串。 大家好,乐字节小乐又来了。上一篇给大家带来的是:Java中的IO流之输入流|乐字节,本文将继续讲述IO流之输出流。showImg(https://segmentfault.com/img/bVbvQx1?w=600&h=338);...

    CoderStudy 评论0 收藏0
  • Java编程基础22——IO(字符)&字符其他内容&递归

    摘要:字符流字符流是什么字符流是可以直接读写字符的流字符流读取字符就要先读取到字节数据然后转为字符如果要写出字符需要把字符转为字节再写出类的方法可以按照字符大小读取通过项目默认的码表一次读取一个字符赋值给将读到的字符强转后打印字符流类的方法可以 1_字符流FileReader 1.字符流是什么 字符流是可以直接读写字符的IO流 字符流读取字符, 就要先读取到字节数据, 然后转为字符. ...

    BoYang 评论0 收藏0

发表评论

0条评论

tommego

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<