精华内容
下载资源
问答
  • Java之IO流---字符流

    千次阅读 2016-09-28 00:00:29
    1.1 字符流的由来在上篇,我提到过用字节流读取中文汉字打印在控制台上,会出现乱码的情况,原因就赘述了。可见,对于字符的操作,强大如斯的字节流也有失利的时候。这个时候我们本篇的主角—字符流就登上了历史的...

    1.概述

    上篇Java之IO流—字节流我们详细的讲解了IO体系与字节流的各类用法,本篇继续梳理字符流。

    1.1 字符流的由来

    在上篇,我提到过用字节流读取中文汉字打印在控制台上,会出现乱码的情况,原因就不赘述了。可见,对于字符的操作,强大如斯的字节流也有失利的时候。这个时候我们本篇的主角—字符流就登上了历史的舞台,展现出它强大的魅力。字符流是建立在字节流之上的,它能够提供字符层次的编码和解码

    对于字符的操作,我们当然首选字符流。同时,转换流也为我们建立了字节流到字符流的桥梁,使我们对数据的处理更加灵活。但是也要注意一些细节,对于从转换流获得的字符流,它读取的字符必须在编码表中可以查找的到,否则会造成乱码。对于像图片、视频这样的文件就不适宜用字符流来处理。可以这样形象的理解字符流, 字符流 = 字节流+编码表

    编码将字符数据转化为字节数据,解码将字节数据转化为字符数据。

    1.2 编码表

    计算机只能识别二进制数据,早期由来是电信号。为了方便应用计算机,让它可以识别各个国家的文字。
    就将各个国家的文字用数字来表示,并一一对应,形成一张表。

    编码表的定义

    编码表由字符及其对应的数值组成的一张表
    

    常见编码表

    ASCII:美国标准信息交换码。 一种使用7个或8个二进制位进行编码的方案
    ISO8859-1:拉丁码表。欧洲码表 用一个字节的8位表示。
    
    GB2312:中国的中文编码表。
    GBK:中国的中文编码表升级,融合了更多的中文文字符号。
    GB18030:GBK的取代版本
    BIG-5码 :通行于台湾、香港地区的一个繁体字编码方案,俗称“大五码”。
    
    Unicode:国际标准码,融合了多种文字。所有文字都用两个字节来表示,Java语言使用的就是unicode
    
    UTF-8:最多用三个字节来表示一个字符。它定义了一种“区间规则”,这种规则可以和ASCII编码保持最大程度的兼容:
            它将Unicode编码为00000000-0000007F的字符,用单个字节来表示
            它将Unicode编码为00000080-000007FF的字符用两个字节表示
            它将Unicode编码为00000800-0000FFFF的字符用3字节表示
    

    2. 字符流

    字符流是Java的io流的两大分支之一,被设计用来处理字符数据,弥补字节流对字符数据操作的短板。

    Writer与Reader这两个抽象类是所有字符输出流与字符输入流的基类,研究字符流,先从他们开始。

    字符流的继承体系在上篇已经展示了,为了加深印象,再贴一遍。
    IO流的继承体系图

    2.1 Writer

    写入字符流的抽象类。子类必须实现的方法仅有 write(char[], int, int)、flush() 和 close()。但是,多数子类将重写此处定义的一些方法,以提供更高的效率和/或其他功能。

    2.11 方法摘要

    主要定义了写的一些方法规范。在之后讲述中,子类只会给出特有方法以示区别。

     Writer append(char c) 
              将指定字符添加到此 writer。 
     Writer append(CharSequence csq) 
              将指定字符序列添加到此 writer。 
     Writer append(CharSequence csq, int start, int end) 
              将指定字符序列的子序列添加到此 writer.Appendable。 
    abstract  void close() 
              关闭此流,但要先刷新它。 
    abstract  void flush() 
              刷新该流的缓冲。 
     void write(char[] cbuf) 
              写入字符数组。 
    abstract  void write(char[] cbuf, int off, int len) 
              写入字符数组的某一部分。 
     void write(int c) 
              写入单个字符。 
     void write(String str) 
              写入字符串。 
     void write(String str, int off, int len) 
              写入字符串的某一部分。 
    

    2.12 FileWriter

    FileWriter是用来写入字符数据到文件的一个便捷实现类,它继承自OutputStreamWriter,它的构造方法假定默认字符编码和默认字节缓冲区大小都是可接受的(实际上使用的是OutputStreamWriter来构造的,包装了一个FileOutputStream对象)。

    要自己指定字符编码和字节缓冲区大小,可以使用 FileOutputStream 对象来构造一个 OutputStreamWriter,在通过得到的转换流来写入。

    底层平台决定了文件是否可用或是否可以被创建。某些平台可能一次只允许一个 FileWriter(或其他文件写入对象)打开文件进行写入,因此如果已经打开相关文件,则再次使用FileWriter来打开文件会失败。

    FileWriter 用于写入字符流。要写入原始字节流,请考虑使用 FileOutputStream。

    2.12.1 构造方法摘要

    FileWriter(File file) 
              根据给定的 File 对象构造一个 FileWriter 对象。 
    FileWriter(File file, boolean append) 
              根据给定的 File 对象构造一个 FileWriter 对象。 
    FileWriter(FileDescriptor fd) 
              构造与某个文件描述符相关联的 FileWriter 对象。 
    FileWriter(String fileName) 
              根据给定的文件名构造一个 FileWriter 对象。 
    FileWriter(String fileName, boolean append) 
              根据给定的文件名以及指示是否附加写入数据的 boolean 值来构造 FileWriter 对象。 
    

    此类方法与父类同,就不贴出了。

    2.12.2使用示例

    public class FileWriterReview {
        public static final String LINE_SEPARATOR = System.getProperty("line.separator");
        public static void main(String[] args) {
            FileWriter fw = null;
            try {
                 fw = new FileWriter("fw.txt",true); // 设置true表示附加内容
                 char[] cbuf = new char[]{'h','e','l','l','o'};
                fw.write(cbuf);
                fw.write(LINE_SEPARATOR); // 添加换行
                fw.write("写入字符串");
                fw.append("附加内容");
                //Returns the name of the character encoding being used by this stream. 
                System.out.println(fw.getEncoding()); 
            } catch (IOException e) {
                e.printStackTrace();
            }finally{
                if (fw!=null) {
                    try {
                        fw.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }

    2.13 OutputStreamWriter

    OutputStreamWriter 是字符流通向字节流的桥梁:可使用指定的 charset(字符集) 将要写入流中的字符编码成字节。它使用的字符集可以由名称指定或显式给定,否则将接受平台默认的字符集。
    也就是说,我们使用OutputStreamWriter对象的相关Write方法进行字符数据写入的时候,会调用相关编码转换器的相关Write方法,先对写入的字符进行编码,得到对应的字节数据,然后被写入到相关文件等输出端。对字符数据的编码使用由我们指定的字符集或默认平台的字符集,来得到对应的字节数据。

    每次调用 write() 方法,实际上都是调用在构造OutputStreamWriter对象时创建的编码转换器(StreamEncoder)的相关方法,由编码器来对给定字符进行相关编码(由我们指定的字符集或默认平台的),然后再进行写入。在写入底层输出流之前,得到的这些字节将在缓冲区中累积。可以指定此缓冲区的大小,不过,默认的缓冲区对多数用途来说已足够大。

    注意,传递给 write() 方法的字符没有缓冲,直接调用StreamEncoder的相关方法进行写入。 因此为了获得最高效率,可考虑将 OutputStreamWriter 包装进 BufferedWriter 中,以避免频繁调用转换器。例如:

    Writer out = new BufferedWriter(new OutputStreamWriter(System.out));

    2.13.1 构造方法摘要

    OutputStreamWriter(OutputStream out) 
              创建使用默认字符编码的 OutputStreamWriter。 
    OutputStreamWriter(OutputStream out, Charset cs) 
              创建使用给定字符集的 OutputStreamWriter。 
    OutputStreamWriter(OutputStream out, CharsetEncoder enc) 
              创建使用给定字符集编码器的 OutputStreamWriter。 
    OutputStreamWriter(OutputStream out, String charsetName) 
              创建使用指定字符集的 OutputStreamWriter。 
    

    2.13.2 使用示例

    public class OutputStreamWriterReview {
        public static void main(String[] args) throws IOException {
    //      test1();
            test2();
        }
    
        private static void test2() throws IOException {
           // 通过转换流,将字符以gbk编码成字节并写入本地文件
            OutputStreamWriter osw=new OutputStreamWriter(new FileOutputStream("osw.txt"), "gbk"); // 指定字符集
            osw.write('a');
            osw.write("编码为");
            osw.write("gbk");
            osw.write("你解码吧");
            osw.write("告诉你一个秘密", 0, 5); // 写入字符串的一部分
            osw.flush();
            osw.close();
        }
    
        private static void test1() throws IOException {
            // 往控制台输出
            OutputStreamWriter osw=new OutputStreamWriter(System.out,"utf-8");
            osw.write("你好");  // 写入缓冲区
            osw.flush();    
            osw.close();    
        }
    }
    

    2.14 BufferedWriter

    BufferedWriter使用装饰器模式,对Writer类的子类提供缓存机制。写操作首先会缓存数据到内置缓冲区中,当缓冲区不足以装下要写的数据时,才会调用flushBuffer刷新缓冲区,并将数据一次写入。因为减少了与底层交互的次数,因此提高了单个字符读写的效率。

    • 构造BufferedWriter可以指定缓冲区的大小。默认缓冲区的大小为8192个int,一般够用。

    • BufferedWriter提供了 newLine() 方法,可以读取当前平台系统属性line.separator定义的换行符并写入。通过System.getProperty(“line.separator”)可获取当前平台对应的换行符。并非所有平台都使用新行符 (‘\n’) 来终止各行。

    通常 Writer 将其输出立即发送到底层字符或字节流,开销很高。所以可以用BufferedWriter 包装这些Writer(如 FileWriters 和 OutputStreamWriters),来提高效率。例如,

     PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter("foo.out")));
    

    2.14.1 构造方法摘要与方法摘要

    1.构造方法摘要

    BufferedWriter(Writer out) 
              创建一个使用默认大小输出缓冲区的缓冲字符输出流。 
    BufferedWriter(Writer out, int sz) 
              创建一个使用给定大小输出缓冲区的新缓冲字符输出流。 
    

    2. 方法摘要
    列举了它的特有方法

     void newLine()  写入一个行分隔符。 
    

    2.14.2 使用示例

    注意:BufferedReader的readLine方法返回的字符串不包含换行符。

    public class BufferedWriterReview {
        public static void main(String[] args) {
            //writeFile1();
            writeFile2();
    
        }
    
        /**
         * readLine读取一行
         * @throws IOException 
         */
        private static void writeFile() throws IOException {
            BufferedWriter bw=new BufferedWriter(new FileWriter("bw2.txt"));
            BufferedReader br=new BufferedReader(new FileReader("fw.txt"));
    
            String buff=null;
            while((buff=br.readLine())!=null){  //读取行,不包含换行符
                //将读取的行内容写入文件,偏移量为0,写入长度为buff的长度
                bw.write(buff, 0,buff.length());
                bw.newLine(); // 添加换行
            }
    
            br.close();
            bw.close();
        }
    
    
        /**
         * read方法
         */
        private static void writeFile0() throws IOException {
            BufferedWriter bw=new BufferedWriter(new FileWriter("bw.txt"));
            BufferedReader br=new BufferedReader(new FileReader("fw.txt"));
            char buff[] = new char[1024];
            int len;
            while((len=br.read(buff))!=-1){
                bw.write(buff, 0, len);
            }
    
            br.close();
            bw.close();
        }
    }
    

    2.15 PrintWriter

    提供打印功能的字符输出流:向文本输出流打印对象的格式化表示形式。此类实现在 PrintStream 中的所有 print 方法。它不包含用于写入原始字节的方法,对于这些字节,程序应该使用未编码的字节流进行写入。

    • 与 PrintStream 类不同,如果启用了自动刷新,只有在调用 println或printf 或 format 方法时才会完成自动刷新,而不是每当正好输出换行符时才完成。这些方法使用平台自有的行分隔符概念,而不是换行符。

    • 除了某些构造方法可能抛出异常,此类中的方法不会抛出 I/O 异常,方法内部都默认自己捕获了异常。可以调用 checkError() 查询是否出现错误。

    2.15.1 构造方法摘要

    通过构造方法可知,它即可操作文件,也可以操作字节输出流与字符输出流

    PrintWriter(File file) 
              使用指定文件创建不具有自动行刷新的新 PrintWriter。 
    PrintWriter(File file, String csn) 
              创建具有指定文件和字符集且不带自动刷行新的新 PrintWriter。 
    PrintWriter(OutputStream out) 
              根据现有的 OutputStream 创建不带自动行刷新的新 PrintWriter。 
    PrintWriter(OutputStream out, boolean autoFlush) 
              通过现有的 OutputStream 创建新的 PrintWriter。 
    PrintWriter(String fileName) 
              创建具有指定文件名称且不带自动行刷新的新 PrintWriter。 
    PrintWriter(String fileName, String csn) 
              创建具有指定文件名称和字符集且不带自动行刷新的新 PrintWriter。 
    PrintWriter(Writer out) 
              创建不带自动行刷新的新 PrintWriter。 
    PrintWriter(Writer out, boolean autoFlush) 
              创建新 PrintWriter。 
    

    此类方法大抵都是打印功能。

    2.15.2 使用示例

    启动自动刷新

    • ① PrintWriter pw = new PrintWriter(new FileWriter(“pw2.txt”), true);
    • ② 还是应该调用println()(printf 或 format)的方法才可以,不仅仅自动刷新了,还实现了数据的换行。

    println() 与下面三行等价:

    bw.write();
    bw.newLine();       
    bw.flush();
    

    如下示例:

    public class PrintWriterDemo {
        public static void main(String[] args) throws IOException {
            // 创建打印流对象
            // PrintWriter pw = new PrintWriter("pw2.txt");
            PrintWriter pw = new PrintWriter(new FileWriter("pw2.txt"), true); // 设置自动刷新
    
    //       pw.print(666);
    //       pw.print("hello"); // 不会自动刷新
    
            pw.println(666);
            pw.println("hello"); // println()(printf 或 format)致使自动刷新
    
            pw.close();
        }
    }   
    
    

    2.2 Reader

    用于读取字符流的抽象类。子类必须实现的方法只有 read(char[], int, int) 和 close()。但是,多数子类将重写此处定义的一些方法,以提供更高的效率和/或其他功能。

    2.21 方法摘要

    abstract  void close() 
              关闭该流并释放与之关联的所有资源。 
     void mark(int readAheadLimit) 
              标记流中的当前位置。 
     boolean markSupported() 
              判断此流是否支持 mark() 操作。 
     int read() 
              读取单个字符。 
     int read(char[] cbuf) 
              将字符读入数组。 
    abstract  int read(char[] cbuf, int off, int len) 
              将字符读入数组的某一部分。 
     int read(CharBuffer target) 
              试图将字符读入指定的字符缓冲区。 
     boolean ready() 
              判断是否准备读取此流。 
     void reset() 
              重置该流。 
     long skip(long n) 
              跳过字符。 
    

    2.22 FileReader

    FileReader是用来读取字符文件的一个便捷实现类,它继承自InputStreamReader,它的构造方法假定默认字符编码和默认字节缓冲区大小都是可接受的(实际上使用的是InputStreamReader来构造的,包装了一个FileInputStream对象)。
    要自己指定字符编码和字节缓冲区大小,可以使用 FileInputStream 对象来构造一个 InputStreamReader,在通过得到的转换流来读取。

    • FileReader 用于读取字符流。要读取原始字节流,可以考虑使用 FileInputStream。

    2.22.1 构造方法摘要

    FileReader(File file) 
              在给定从中读取数据的 File 的情况下创建一个新 FileReader。 
    FileReader(FileDescriptor fd) 
              在给定从中读取数据的 FileDescriptor 的情况下创建一个新 FileReader。 
    FileReader(String fileName) 
              在给定从中读取数据的文件名的情况下创建一个新 FileReader。 
    

    2.22.2 使用示例

    public class FileReaderReview {
        public static void main(String[] args) {
            //ReadMethod1();
            ReadMethod2();
        }
    
        private static void ReadMethod2() {
            FileReader fr = null;
            try {
                fr= new FileReader("fw.txt");
                char[] buff = new char[1024];
                int len=0;
                // 每次将读取的内容放入一个数组缓冲区,读到内容返回读取的字符长度,否则返回-1
                while((len=fr.read(buff))!=-1){  
                    System.out.print(new String(buff, 0, len));
                }
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }finally{
                if(fr!=null){
                    try {
                        fr.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
    
        }
    
        private static void ReadMethod1() {
            FileReader fr = null;
            try {
                fr = new FileReader("fw.txt");
                int ch;
                while((ch=fr.read())!=-1){  // 每次读取一个字符,读完数据返回-1
                    System.out.print((char)ch);
                }
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }finally{
                if(fr!=null){
                    try {
                        fr.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }

    2.23 InputStreamReader

    InputStreamReader 是字节流通向字符流的桥梁:它使用指定的 charset 读取字节并将其解码为字符。它使用的字符集可以由名称指定或显式给定,或者可以接受平台默认的字符集。
    也就是说,我们使用InputStreamReader对象的相关read方法进行字符数据读取的时候,会调用相关解码转换器的相关read方法,先对读取的字符进行解码,得到对应的字符数据,然后就可以使用得到的字符数据。对字节数据的解码使用由我们指定的字符集或默认平台的字符集,来得到对应的字符数据。

    • 每次调用 InputStreamReader 中的一个 read() 方法都会导致从底层输入流读取一个或多个字节。要启用从字节到字符的有效转换,可以提前从底层流读取更多的字节,使其超过满足当前读取操作所需的字节。

    为了达到最高效率,可要考虑在 BufferedReader 内包装 InputStreamReader。例如:

     BufferedReader in= new BufferedReader(new InputStreamReader(System.in));
    

    2.23.1 构造方法摘要

    可以指定字符集来解码字节文件

    InputStreamReader(InputStream in) 
              创建一个使用默认字符集的 InputStreamReader。 
    InputStreamReader(InputStream in, Charset cs) 
              创建使用给定字符集的 InputStreamReader。 
    InputStreamReader(InputStream in, CharsetDecoder dec) 
              创建使用给定字符集解码器的 InputStreamReader。 
    InputStreamReader(InputStream in, String charsetName) 
              创建使用指定字符集的 InputStreamReader。 
    

    特别指出一个特别的方法

    String getEncoding() 返回此流使用的字符编码的名称。 
    

    2.23.2 使用示例

    public class InputStreamReaderReview {
        public static void main(String[] args) throws Exception {
    
            review3();
        }
    
        private static void review3() throws IOException, FileNotFoundException {
            // 指定按gbk将字节解码为字符读取到输入流中
            InputStreamReader isr=new InputStreamReader(new FileInputStream("osw.txt"), "gbk");
            char[] cbuf=new char[1024];
            int len=-1;
            while ((len=isr.read(cbuf))!=-1) {
                System.out.println(new String(cbuf, 0, len));
            }
            isr.close();
        }
    
        private static void review1() throws IOException {
            // 使用BufferedReader提高效率
            BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
            String s=null;
            while(!(s=br.readLine()).equals("over"))
            {
                System.out.println(s.toUpperCase());
            }
            br.close();
        }
    
        private static void review2() throws Exception {
            FileOutputStream fos=new FileOutputStream(new File("D:\\changeio.txt"));
            // 指定以gbk将字符编码成字节写入流中
            OutputStreamWriter osw=new OutputStreamWriter(fos,"GBK"); 
            osw.write("设为GBK写入");
            osw.close();
    
            FileInputStream fis = new FileInputStream(new File("D:\\changeio.txt"));
            // 指定按gbk将字节解码为字符读取到输入流中
            InputStreamReader isr = new InputStreamReader(fis,"GBK"); 
            char[] cbuf = new char[1024];
            int len=0;
            while ((len=isr.read(cbuf))!=-1) {
                System.out.println(new String(cbuf,0,len));
            }
            isr.close();
        }
    }
    

    2.24 BufferedReader

    从字符输入流中读取文本,缓冲各个字符,从而实现字符、数组和行的高效读取。

    • 构造BufferedReader可以指定缓冲区的大小。通常默认大小(8192个int)已经足够
    • 使用readLine方法可以很方便的读取一行,不过并不包含换行符

    通常,Reader 所作的每个读取请求都会导致对底层字符或字节流进行相应的读取请求。因此,建议用 BufferedReader 包装所有其 read() 操作可能开销很高的 Reader(如 FileReader 和 InputStreamReader)。例如,

     BufferedReader in= new BufferedReader(new FileReader("foo.in"));
    

    2.24.1 构造方法摘要与方法摘要

    1.构造方法

    BufferedReader(Reader in) 
              创建一个使用默认大小输入缓冲区的缓冲字符输入流。 
    BufferedReader(Reader in, int sz) 
              创建一个使用指定大小输入缓冲区的缓冲字符输入流。 
    

    2.特殊方法

    String readLine()  读取一个文本行。 
    

    2.24.2 使用示例

    注意:使用BufferedReader读取的一行不包含换行符

    public class BufferedReaderReview {
        public static void main(String[] args) {
            readFile();
        }
    
        private static void readFile() {
            FileReader fr=null;
            CustomBufferedReader br=null;
            try {
                fr=new FileReader("jar.txt");
                br = new CustomBufferedReader(fr);
                String line=null;
                while((line=br.readLine())!=null){//不包含 line-termination characters
                    System.out.println(br.getLineNumber()+":"+line);
                }
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }finally{
                if(br!=null){
                    try {
                        br.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }

    2.24.3 自定义BufferedReader与BufferedWriter

    上面用到了CustomBufferedReader,它是一个自定义的BufferedReader。可以戳java学习笔记之BufferedReader与BufferedWriter看看实现

    3 RandomAccessFile

    RandomAccessFile类不属于流,是Object类的子类。但它融合了InputStream和OutputStream的功能。支持对文件的随机访问读取和写入。

    随机访问文件的行为类似存储在文件系统中的一个大型 byte 数组。存在指向该隐含数组的光标或索引,称为文件指针;输入操作从文件指针开始读取字节,并随着对字节的读取而前移此文件指针。如果随机访问文件以读取/写入模式创建,则输出操作也可用;输出操作从文件指针开始写入字节,并随着对字节的写入而前移此文件指针。写入隐含数组的当前末尾之后的输出操作导致该数组扩展。该文件指针可以通过 getFilePointer 方法读取,并通过 seek 方法设置。

    通常,如果此类中的所有读取例程在读取所需数量的字节之前已到达文件末尾,则抛出 EOFException(是一种 IOException)。如果由于某些原因无法读取任何字节,而不是在读取所需数量的字节之前已到达文件末尾,则抛出 IOException,而不是 EOFException。需要特别指出的是,如果流已被关闭,则可能抛出 IOException。

    3.1 构造方法摘要

    RandomAccessFile(String name, String mode) 
              创建从中读取和向其中写入(可选)的随机访问文件流,该文件具有指定名称。 
    RandomAccessFile(File file, String mode) 
              创建从中读取和向其中写入(可选)的随机访问文件流,该文件由 File 参数指定。        
              将创建一个新的 FileDescriptor 对象来表示此文件的连接。 mode 参数指定用以打开文件的访问模式。
        允许的值及其含意为: 
    
        值       含意
        "r"     以只读方式打开。调用结果对象的任何 write 方法都将导致抛出 IOException。  
        "rw"    打开以便读取和写入。如果该文件尚不存在,则尝试创建该文件。  
        "rws"   打开以便读取和写入,对于 "rw",还要求对文件的内容或元数据的每个更新都同步写入到底层存储设备。  
        "rwd"   打开以便读取和写入,对于 "rw",还要求对文件内容的每个更新都同步写入到底层存储设备。  
        "rwd" 模式可用于减少执行的 I/O 操作数量。使用 "rwd" 仅要求更新要写入存储的文件的内容;
        使用 "rws" 要求更新要写入的文件内容及其元数据,这通常要求至少一个以上的低级别 I/O 操作。 
    

    3.2 方法摘要

    方法大抵都是一些读写操作,下面只列出一些特殊的方法

    FileDescriptor getFD() 
              返回与此流关联的不透明文件描述符对象。 
     long getFilePointer() 
              返回此文件中的当前偏移量。 
     String readLine() 
              从此文件读取文本的下一行。 
     String readUTF() 
              从此文件读取一个字符串。 
     void writeUTF(String str) 
              使用 modified UTF-8 编码以与机器无关的方式将一个字符串写入该文件。 
     void seek(long pos) 
              设置到此文件开头测量到的文件指针偏移量,在该位置发生下一个读取或写入操作。 
    int skipBytes(int n) 
              尝试跳过输入的 n 个字节以丢弃跳过的字节。 
    

    3.3 使用示例

    public class RandomAccessFileDemo {
    
        public static void main(String[] args) throws IOException {
            //write();
            read();
        }
    
        /**
         * 读取数据
         * @throws IOException
         */
        private static void read() throws IOException {
            // 创建随机访问流对象
            RandomAccessFile raf = new RandomAccessFile("raf.txt", "rw");
    
            String s = raf.readUTF();
            System.out.println(s);
            System.out.println("当前文件指针的位置是:" + raf.getFilePointer());
    
            int i = raf.readInt();
            System.out.println(i);
            // 该文件指针可以通过 getFilePointer方法读取,并通过 seek 方法设置。
            System.out.println("当前文件指针的位置是:" + raf.getFilePointer());
    
            char ch = raf.readChar();
            System.out.println(ch);
            System.out.println("当前文件指针的位置是:" + raf.getFilePointer());
    
    
            // 使用seek跳转到指定位置
            raf.seek(16);
            ch = raf.readChar();
            System.out.println(ch);
        }
        /**
         * 写入数据到文件
         * @throws IOException
         */
        private static void write() throws IOException {
            // 创建随机访问流对象
            RandomAccessFile raf = new RandomAccessFile("raf.txt", "rw");
    
            // 写入
            raf.writeUTF("你好啊~");  // utf-8 一个汉字3个字节
            raf.writeInt(66);
            raf.writeChar('u');
    
            raf.close();
        }
    
        // output
        //  你好啊~
        //  当前文件指针的位置是:12
        //  66
        //  当前文件指针的位置是:16
        //  u
        //  当前文件指针的位置是:18
        //  u
    
    }

    参考文档:JavaSE API docs

    源码

    展开全文
  • Java IO 2-字节流与字符流

    千次阅读 2018-05-22 23:01:40
    输入输出流又分为字节流与字符流,所以总共加起来有如下四种流: InputStream: 字节输入流 Reader: 字符输入流 OutputStream: 字节输出流 Writer: 字符输出流 四者之间的关系如下: ...

      FILE类只参与文件的创建删除等操作,而不对文件本身内容进行修改。如果要处理文件内容,就需要使用流来进行操作。

    1. 流的分类

    流分为输入流与输出流。
    输入输出流又分为字节流与字符流,所以总共加起来有如下四种流:

    • InputStream: 字节输入流
    • Reader: 字符输入流
    • OutputStream: 字节输出流
    • Writer: 字符输出流
      四者之间的关系如下:

    字节输入流与输出流

    字符输入流与输出流

      字节流与字符流操作的本质区别只有一个:字节流是原生的操作,而字符流是经过处理后的操作。

      在进行网络数据传输、磁盘数据保存所保存所支持的数据类型只有:字节。
    而所有磁盘中的数据必须先读取到内存后才能进行操作,而内存中会帮助我们把字节变为字符。字符更加适合处理。
    中文。

      另外,由于IO操作属于资源处理操作,所以在使用完毕之后必须进行关闭。

    2. 字节输出流OutputStream

      OutputStream是字节输出流的顶层抽象类,它的定义如下:

    public abstract class OutputStream implements Closeable, Flushable

      它实现了两个接口,这两个接口中各自只有一个抽象方法,所以这两个接口又称为标识接口。
      实现的抽象方法定义如下:

    // Closeable
    public void close() throws IOException;
    
    // Flushable
    void flush() throws IOException

      OutputStream类中常用的方法:

    // 将给定的字节数组内容全部输出
    public void write(byte b[]) throws IOException
    
    // 将部分字节数组内容输出
    public void write(byte b[], int off, int len) throws IOException
    
    // 输出单个字节
    public abstract void write(int b) throws IOException;

      因为OutputStream是顶层抽象类,所以我们一般使用它的一个实现子类FileOutputStream进行父类的实例化。

      下面是FileOutputStream的两个构造。

    // 接收File类,输出时会覆盖原有内容
    public FileOutputStream(File file) throws FileNotFoundException
    
    // 接收File类,输出时在原有内容后面追加
    public FileOutputStream(File file, boolean append)

      我们看下面的例子

    import java.io.File;
    import java.io.FileOutputStream;
    import java.io.OutputStream;
    
    /**
     * 测试路径:E:\IO\demo.txt
     */
    
    public class Test {
        public static void main(String[] args) throws Exception {
            File file = new File("E:\\IO\\demo.txt");
            // 如果父目录不存在,创建
            if(!file.getParentFile().exists()) {
                file.getParentFile().mkdirs();
            }       
            // 字节输出流
            OutputStream outputStream = new FileOutputStream(file);
            // 输出内容
            String msg = "hello world";
            // 字节输出流只接受字节数组,所以要将字符串转换为字节数组
            outputStream.write(msg.getBytes());
            // 关闭输出流
            outputStream.close();
        }
    }

    运行程序前,测试文件夹如下:

    运行前

    运行后,如下:

    运行后

      注意,只要是输出流,输出文件如果不存在,JDK会自动帮用户创建,不需要用户手工调用createNewFile()。但是文件路径必须存在,所以一定要在程序中检查父路径是否存在。

      JDK还提供了一种自动关闭流的接口。

    // 该接口也只有一个抽象方法,为标识接口
    public interface AutoCloseable {
        void close() throws Exception;
    }

      关于流的四个顶层抽象类都实现了该接口,都可以直接使用。

      虽然使用该接口可以省掉恼人的关闭流操作,可是它还要与try…catch一起使用,这样变得更加复杂了,操作如下:

    import java.io.File;
    import java.io.FileOutputStream;
    import java.io.OutputStream;
    
    /**
     * 测试路径:E:\IO\demo.txt
     */
    
    
    public class Test {
        public static void main(String[] args) throws Exception {
            File file = new File("E:\\IO\\demo.txt");
            if(!file.getParentFile().exists()) {
                file.getParentFile().mkdirs();
            }
    
            try(OutputStream output = new FileOutputStream(file)) {// 实现了AutoCloseable接口的字节输出流要定义在try内 
                String str = "hello world";
                output.write(str.getBytes());
            } catch(Exception e) {
                e.printStackTrace();
            }
        }
    }

      这种反人类的操作大家自己取舍。

    3. 字节输入流InputStream

      InputStream与OutputStream一样,时字节输入的顶层抽象类,具体应用时使用的它的实现子类。

    public abstract class InputStream implements Closeable

      对应字节输出流,字节输入流的常用方法为 read 方法,这里我们要注意它的返回值。

    // 读取数据到字节数组中,返回数据的读取个数
    // 如果此时开辟的字节数组大小大于读取的数据大小,则返回的就是读取个数
    // 如果要读取的数据大于数组的内容,那么这个时候返回的就是数组长度
    // 如果没有数据了还在读,则返回-1
    public int read(byte b[]) throws IOException (最常用方法)
    
    // 读取部分数据到字节数组中,每次只读取传递数组的部分内容
    // 如果读取满了则返回长度(len)
    // 如果没有读取满则返回读取的数据个数
    // 如果读取到最后没有数据了返回-1
    public int read(byte b[], int off, int len) throws IOException
    
    // 读取单个字节,每次读取一个字节的内容,直到没有数据了返回-1
    public abstract int read() throws IOException;
    

      看下面的例子,我们读取的文件为上个例子中写入”hello world”的文件。

    import java.io.File;
    import java.io.FileInputStream;
    import java.io.InputStream;
    
    /**
     * 测试路径:E:\IO\demo.txt
     */
    
    
    public class Test {
        public static void main(String[] args) throws Exception {
            File file = new File("E:\\IO\\demo.txt");
            // 输入流和输出流不同,不会自动创建文件,所以这里要保证文件存在
            if(file.exists()) {
                InputStream in = new FileInputStream(file);
                // 存放读取数据的字节数组
                byte[] data = new byte[1024];
                // 将内容读取到数组中
                int len = in.read(data);
                // 将数组内容转换为字符串,便于我们观察结果
                String result = new String(data, 0, len);
                System.out.println(result);
                in.close();
            }
        }
    }

    运行结果:

    运行结果

    4. 字符输出流Writer

      字符比起字节来说能够更好的处理中文数据,Writer类定义如下:

    public abstract class Writer implements Appendable, Closeable, Flushable

      看下面的例子:

    import java.io.File;
    import java.io.FileWriter;
    import java.io.Writer;
    
    /**
     * 测试路径:E:\IO\demo.txt
     */
    
    
    public class Test {
        public static void main(String[] args) throws Exception {
            File file = new File("E:\\IO\\demo.txt");
    
            // 同字节输出流,一定要保证父路径存在
            if(!file.getParentFile().exists()) {
                file.getParentFile().mkdirs();
            }
            String str = "爱生活爱Java";
            Writer out = new FileWriter(file);
            out.write(str);
            out.close();
        }
    }

    运行前:

    运行前

    运行后:

    运行后

      Writer类的结构与方法的使用与OutputStream非常相似,只是Writer类对于中文的支持很好并且提供了直接写入String的方法而已,而OutputStream的输出方法writer()必须先将字符串转为字节数组再进行参数传入。所以以后输出字符串中文的场景,最好使用Writer类,能省下很多的功夫。

    5. 字符输入流Reader

      Reader依然是一个抽象类。使用时使用它的实现子类 FileReader。

      Writer类中有直接接受字符串的write方法,而同作为字符操作流的Reader是没有提供的,所以Reader也只能通过字符数组进行操作。

      看下面的例子,文件使用上个例子中被写入的文件。

    import java.io.File;
    import java.io.FileReader;
    import java.io.Reader;
    
    /**
     * 测试路径:E:\IO\demo.txt
     */
    
    
    public class Test {
        public static void main(String[] args) throws Exception {
            File file = new File("E:\\IO\\demo.txt");
    
            // 保证文件存在才能进行操作
            if(file.exists()) {
                Reader in = new FileReader(file);
                char data[] = new char[1024];
                int len = in.read(data);
                String str = new String(data, 0, len);
                System.out.println(str);
                in.close();
            }
        }
    }

    运行结果:

    运行结果

    展开全文
  • 面试必问的 Java 字节流与字符流

    千次阅读 2019-02-25 07:00:00
    一些人不屑于看,看了标题就私信我“能能写点高级的,看了这标题我就知道内容了,再这样我就取关了!” 但是也有人表示喜欢看。“内容虽然基础,但是看完后我有了新的认知!” 所以,我的尴尬的取关数据是时候给...

    点击上方“业余草”,选择“置顶公众号”

    第一时间获取技术干货和业界资讯!

    640?wx_fmt=png

     

    最近,我写的都是一些基础知识。一些人不屑于看,看了标题就私信我“能不能写点高级的,看了这标题我就知道内容了,再这样我就取关了!”

    但是也有人表示喜欢看。“内容虽然基础,但是看完后我有了新的认知!”

    所以,我的尴尬的取关数据是时候给大家展示一下了。

    640

    最近 30 天的趋势图如下所示。

    640

    我要感谢一部分网友通过转发、评论等形式对我的支持!谢谢你们!


    好了,下面我们开始今天的内容。

    字节流和字符流其实很好理解!

    字节流就是 Byte 流,字节就是 Byte。

    字符流就是 Character 流,字符就是 Character。

    这里面有两个单位换算大家需要记住一下。

    • 1 byte = 8 bit

    • 1 char = 2 byte = 16 bit

    虽然 1 bit 才是数据真正的最小单位,但 1 bit 的信息量太少了。要表示一个有用的信息,需要好几个 bit 一起表示。所以大多数情况下,字节是数据最小的基本单位。

    比如,我们熟知的基本型的大小都是 8 bit(也就是1字节)的整数倍:

    • boolean: 1 byte

    • short: 2 byte

    • int: 4 byte

    • float: 4 byte

    • long: 8 byte

    • double: 8 byte

    到这里,我们认识的都是字节。但是,Java I/O 的编码系统提供的 Java IO 库有两个支系,面向字节流的 InputStream 和 OutputStream;面向字符的 Reader 和 Writer。

    为什么要有字符流呢?那是因为英文,我们可以用字节来表示,但是中文、日文、韩文等没法用字节来表示了,所有人们就想到了新的字符编码集。比如,Unicode 字符集,GB 18030,GBK,Big5,ISO-8859-1 等。

    所以,最终就是一个字符用 1 个、2 个或 4 个字节组成。总而言之,一切都是字节流,其实没有字符流这个东西。字符只是根据编码集对字节流翻译之后的产物。

    所以,字节流的 InputStream 和 OutputStream 才是一切的基础。实际总线中流动的只有字节流。需要对字节流做特殊解码才能得到字符流。Java 中负责从字节流向字符流解码的桥梁是InputStreamReader 和 InputStreamWriter。

    看下面的 InputStreamReader 和 OutputStreamWriter 的结构图。

    640

    实际负责编码和解码的是 StreamDecoder 类和 StreamEncoder 类。编码过程中必须指定使用的字符编码集 Charset。所以 InputStreamReader 和 OutputStreamWriter 的构造器都带有 Charset 类型的参数。

    如果没有指定编码集,将使用系统默认编码集。而我们经常使用的 FileInputReader 和 FileOutputWriter 就是 InputStreamReader 和 OutputStreamWriter 的派生类。

    到现在,你是不是想起了那句话。“世界上本来没有路,走的人多了,也就变成了路。”

    计算机中本没有字符流,一开始只适用于英文,但是互联网属于全人类的,所以人们又搞出了字符流。字符只是包装的字节而已。

    原文链接:浅谈 Java 中的字节流与字符流

    640

    10T技术资源大放送!包括但不限于:C/C++,Linux,Python,Java,PHP,人工智能,GO等等。在公众号内回复对应关键字或框架名字,即可免费获取!!

    640?wx_fmt=png

     你再主动一点点 640?  我们就有故事了

    展开全文
  • Java I/O(字节流、字符流与转换流)

    千次阅读 2019-04-26 12:06:18
    **File类支持文件内容处理,如果要处理文件内容,必须要通过流的...字节流与字符流操作的本质区别只有一个:字节流是原生的操作,而字符流是经过处理后的操作。 在进行网络数据传输、磁盘数据保存所保存所支持的...

    **File类不支持文件内容处理,如果要处理文件内容,必须要通过流的操作模式来完成。流分为输入流和输出流。
    在java.io包中,流分为两种:字节流与字符流:

    • 字节流:InputStream、OutputStream
    • 字符流:Reader、Writer**
      在这里插入图片描述
      在这里插入图片描述

    字节流与字符流操作的本质区别只有一个:字节流是原生的操作,而字符流是经过处理后的操作。
    在进行网络数据传输、磁盘数据保存所保存所支持的数据类型只有:字节。

    而所有磁盘中的数据必须先读取到内存后才能进行操作,而内存中会帮助我们把字节变为字符。字符更加适合处理中文。

    不管使用的是字节流还是字符流,其基本的操作流程几乎是一样的,以文件操作为例。
    根据文件路径创建File类对象 ;

    • 根据字节流或字符流的子类实例化父类对象 ;

    • 进行数据的读取或写入操作

    • 关闭流(close())

    对于IO操作属于资源处理,所有的资源处理操作(IO操作、数据库操作、网络)最后必须要进行关闭。

    字节输出流(OutputStream)
    OutputStream类的定义结构

    public abstract class OutputStream implements Closeable, Flushable
    

    OutputStream类实现Closeable, Flushable这两个接口,这两个接口中的方法:

    Closeable: public void close() throws IOException;
    Flushable: public void flush() throws IOException;
    

    OutputStream类中定义的其他方法:

    • 将给定的字节数组内容全部输出:public void write(byte b[]) throws IOException

    • 将部分字节数组内容输出:public void write(byte b[], int off, int len) throws IOException

    • 输出单个字节:public abstract void write(int b) throws IOException

    由于OutputStream是一个抽象类,所以要想为父类实例化,就必须要使用子类。由于方法名称都由父类声明好了,所以我们在此处只需要关系子类的构造方法。如果要进行文件的操作,可以使用FileOutputStream类来处理,这个类的构造方法如下:
    接收File类(覆盖):public FileOutputStream(File file) throws FileNotFoundException
    接收File类(追加):public FileOutputStream(File file, boolean append)

    实现文件的内容输出:

    package com.bittech;
    
    import java.io.File;
    import java.io.FileOutputStream;
    import java.io.OutputStream;
    public class Test {
        public static void main(String[] args) throws Exception{
            File file = new File("E:"+File.separator+"1"+File.separator+"test");
            if (!file.getParentFile().exists()) { // 必须保证父目录存在
                file.getParentFile().mkdirs() ; // 创建多级父目录
            }
    // OutputStream是一个抽象类,所以需要通过子类进行实例化,此时只能操作File类
            OutputStream output = new FileOutputStream(file) ;
    // 要求输出到文件的内容
            String msg = "我们都是一家人!" ;
    // 将内容变为字节数组
            output.write(msg.getBytes());
    // 关闭输出
            output.close();
        }
    }
    

    在进行文件输出的时候,所有的文件会自动帮助用户创建,不在需要调用createFile()方法手工创建。
    这个时候程序如果重复执行,并不会出现内容追加的情况而是一直在覆盖。如果需要文件内容追加,则需要调用FileOutputStream提供的另外一种构造方法。

    文件内容的追加:

    package www.bittech;
    
    import java.io.File;
    import java.io.FileOutputStream;
    import java.io.OutputStream;
    
    public class Test {
        public static void main(String[] args) throws Exception{
            File files=new File("E:"+File.separator+"1"+File.separator+"test.txt");
            if(!files.getParentFile().exists()){// 必须保证父目录存在
                files.getParentFile().mkdirs();//创建多级父目录
            }
            //OutputStream是一个抽象类,所以需要通过子类进行实例化,此时只能操作File类
            OutputStream out=new FileOutputStream(files,true);
             要求输出到文件的内容
            String msg="快快乐乐的一家人!\n";
            //将内容变为字节数组
            out.write(msg.getBytes());
             关闭输出
            out.close();
        }
    }
    

    1.输出流如果文件不存在,自动创建
    2.FileOutputStream中 append默认是false会覆盖内容,若为true,则字节写入文件的末尾而不是开头。

    AutoCloseable自动关闭支持
    从JDk1.7开始追加了一个AutoCloseable接口,这个接口的主要目的是自动进行关闭处理,但是这种处理一般不好用,因为使用它必须结合try…catch。

    AutoCloseable接口使用:

    package www.bittech;
    
    class Message implements AutoCloseable{
        public Message(){
            System.out.println("创建一条新消息!");
        }
        public void close() throws Exception{
            System.out.println("[AutoCloseable自动关闭方法!]");
        }
        public void print(){
            System.out.println("www.bittech");
        }
    }
    public class Test {
        public static void main(String[] args) {
            try (Message msg=new Message()){//必须在try中定义对象
                msg.print();
            }catch (Exception e){
    
            }
        }
    }
    

    推荐使用close手工关闭!

    字节输入流:InputStream
    利用了OutputStream实现了程序输出内容到文件的处理,下面使用InputStream类在程序中读取文件内容。
    InputStream类的定义如下:

    public abstract class InputStream implements Closeable
    

    InputStream类只实现了Closeable接口,在InputStream类中提供有如下方法:

    • 读取数据到字节数组中,返回数据的读取个数。如果此时开辟的字节数组大小大于读取的数据大小,则返回的就是读取个数;如果要读取的数据大于数组的内容,那么这个时候返回的就是数组长度;如果没有数据了还在读,则返回-1: public int read(byte b[]) throws IOException.最常用方法
    • 读取部分数据到字节数组中,每次只读取传递数组的部分内容,如果读取满了则返回长度(len),如果没有读取满则返回读取的数据个数,如果读取到最后没有数据了返回-1:public int read(byte b[], int off,int len) throws IOException
    • 读取单个字节,每次读取一个字节的内容,直到没有数据了返回-1:public abstract int read() throws IOException;同OutputStream的使用一样,InputStream是一个抽象类,如果要对其实例化,同样也需要使用子类。如果要对文件进行处理,则使用FileInputStream类。

    实现文件信息的读取:

    package www.bittech;
    
    import java.io.File;
    import java.io.FileOutputStream;
    import java.io.OutputStream;
    
    public class Test {
        public static void main(String[] args) throws Exception{
            File file=new File("E:"+File.separator+"1"+File.separator+"test");
            if(file.exists()) {
                InputStream input = new FileInputStream(file);
                byte[] date = new byte[1024];//每次可以读取的最大数量
                int len = input.read(date);//此时数据读取到数组中
                String result=new String(date,0,len);//将字节数组转换为String
                System.out.println(result);
                input.close();
            }
        }
    }
    

    字符输出流:Writer
    字符适合于处理中文数据,Writer是字符输出流的处理类,这个类的定义如下:

    public abstract class Writer implements Appendable, Closeable, Flushable
    

    与OutputStream相比多了一个Appendable接口。
    在Writer类里面也提供write()方法,而且该方法接收的类型都是char型,要注意的是,Writer类提供了一个直接输出字符串的方法:

    public void write(String str) throws IOException
    

    通过Writer实现输出:

    package www.bittech;
    
    import java.io.File;
    import java.io.Writer;
    import java.io.FileWriter;
    
    
    public class Test {
        public static void main(String[] args) throws Exception{
            File file=new File("E:"+File.separator+"1"+File.separator+"test.txt");
            if(!file.getParentFile().exists()){//必须保证父目录存在
                file.getParentFile().mkdirs();//创建多级父目录
            }
            Writer out=new FileWriter(file,true);
            out.write("今天天气真好!");
            out.close();
        }
    }
    

    字符输入流:Reader
    Reader依然也是一个抽象类。如果要进行文件读取,同样的,使用FileReader。
    在上面讲到的Writer类中提供有方法直接向目标源写入字符串,而在Reader类中没有方法可以直接读取字符串类型,这个时候只能通过字符数组进行读取操作。

    通过文件读取数据:

    package www.bittech;
    
    import java.io.File;
    import java.io.Reader;
    import java.io.FileReader;
    
    
    public class Test {
        public static void main(String[] args) throws Exception{
             1.定义文件路径
            File file=new File("E:"+File.separator+"1"+File.separator+"test.txt");
             2.必须保证文件存在才能进行处理
            if(file.exists()){
                Reader in=new FileReader(file);
                char[] date=new char[1024];//每次可读取的最大数量
                int len=in.read(date);// 将数据读取到字符数组中
                String result=new String(date,0,len);
                System.out.println(result);
                in.close();
            }
        }
    }
    

    字符流适合处理中文,字节流适合处理一切数据类型(对中文支持不好)。

    字节流vs字符流
    使用字节流和字符流从代码形式上区别不大。但是如果从实际开发来讲,字节流一定是优先考虑的,只有在处理中文时才会考虑字符流。因为所有的字符都需要通过内存缓冲来进行处理。所有字符流的操作,无论是写入还是输出,数据都先保存在缓存中。如果字符流不关闭,数据就有可能保存在缓存中并没有输出到目标源。这种情况下就必须强制刷新才能够得到完整数据。

    字符流刷新操作:

    package www.bittech;
    
    import java.io.File;
    import java.io.Writer;
    import java.io.FileWriter;
    
    
    public class Test {
        public static void main(String[] args) throws Exception{
            File file=new File("E:"+File.separator+"1"+File.separator+"test.txt");
            if(!file.getParentFile().exists()){//必须保证父目录存在
                file.getParentFile().mkdirs();//创建多级父目录
            }
            Writer out=new FileWriter(file,true);
            out.write("今天天气真好!");
            out.flush();//写上此语句表示强制清空缓冲内容,所有内容都输出
        }
    }
    

    在以后进行IO处理的时候,如果处理的是图片、音乐、文字都可以使用字节流,而只有处理中文的时候才会使用字符流。

    转换流
    字节流和字符流是可以进行相互转换的。
    OutputStreamWriter:将字节输出流变为字符输出流(Writer对于文字的输出要比OutputStream方便)
    InputStreamReader:将字节输入流变为字符输入流(InputStream读取的是字节,不方便中文的处理)

    它们的继承关系以及构造方法:

    public class OutputStreamWriter extends Writer
    public OutputStreamWriter(OutputStream out)
    
    
    public class InputStreamReader extends Reader
    public InputStreamReader(InputStream in)
    

    实现字节流与字符流的转换:

    package www.bittech;
    
    import java.io.*;
    
    
    public class Test {
        public static void main(String[] args) throws Exception{
            File file=new File("E:"+File.separator+"1"+File.separator+"test.txt");
            if(!file.getParentFile().exists()){//必须保证父目录存在
                file.getParentFile().mkdirs();//创建多级父目录`在这里插入代码片`
            }
            OutputStream output= new FileOutputStream(file);
            Writer out=new OutputStreamWriter(output);//字节流转为字符流
            out.write("今天是你生日吗?");
            out.close();
        }
    }
    

    FileOutputStream、FileInputStream、FileWriter、FileReader之间的继承关系:
    在这里插入图片描述

    展开全文
  • 第一个问题:怎么区分字节流和字符流? 类名以stream结尾的都是字节流;类名以reader或者writer结尾的都是字符流 由于题上问的是输入流,所以暂时是A和D,然后在看 第二个问题:输入流和输出流是相对于什么而言? ...
  • 首先看一下File类的常用方法 •File类的对象不但可以表示文件,还可以表示目录,在程序中一个File类对象...需要注意的是,File对象并能直接对文件进行读/写操作,只能查看文件的属性; 方 法 原 型
  • 字节流与字符流的区别及相互转换

    千次阅读 2017-10-20 08:41:13
    先来看一下流的概念:  在程序中所有的数据都是以流的方式进行传输或保存的,程序需要数据的时候要使用输入流读取数据,而当程序需要将一些数据保存起来的时候,就要使用输出流完成。...字节流与字符流  在ja
  • Java之IO流---字节流,字符流,buffer,file

    千次阅读 2018-05-05 21:38:22
    1.概述1.1 IO流的引入 IO流在...我们可以对它进行如下分类:按处理的数据类型可分为字节流(byte)与字符流(char)按流的流向可分为输入流(in)与输出流(out)按流的功能可分为节点流(Node)和过滤流(Filter)本篇侧重...
  • 上次只写了字节流的操作,现在吧字符流的也补上 同样FileReader和BuuferedReader是读取文件到内存,是属于输入流 FileWriter和BufferedWriter是从内存输出到文件中,属于输出流(都是以内存为参照) 看下...
  • 先来看一下流的概念:      在程序中所有的数据都是以流的方式进行传输或保存的,程序需要数据的时候要使用输入流...字节流与字符流     &amp
  • InputStreamReader及其子类FileReader:(从字节到字符)是个解码过程; OutputStreamWrite及其子类FileWriter:(从字符到字节)是个编码过程。 InputStreamReader这个解码过程中,最主要的就是StreamDecoder类
  • File文件,字节输入,字节输入字符输入,字节输出的详解 File文件概述 1.File类型:用于表示一个文件或者是文件夹的路径的对象(抽象路径名) 2.路径:用于描述文件或者是文件夹的所在路径的所在的字符串 3....
  • 工作中经常遇到java编码问题,...Java读取文件的方式总体可以分为两类:按字节读取和按字符读取。按字节读取就是采用InputStream.read()方法来读取字节,然后保存到一个byte[]数组中,最后经常用new String(byte[]
  • C语言gets()函数:从中读取字符

    千次阅读 2015-10-26 10:59:46
    gets()函数从中读取字符串,直到出现换行符或读到文件尾为止,最后加上NULL作为字符串结束。所读取的字符串暂存在给定的参数string中。 【返回值】若成功则返回string的指针,否则返回NULL。 注意:由于gets...
  • ASCII码可见字符过滤处理

    千次阅读 2018-04-19 10:46:27
    Function/Control Code/Character in ASCIIVersion: 2011-02-15Author: green-waste (at) 163.com【什么是 Function Code 功能码或 Function Character...128 个字符。其中前 32 个, 0-31 ,即 0x00-0x1F...
  • IO

    千次阅读 2016-12-22 15:56:59
    1. 下面哪个属于面向字符的输入? A. BufferedWriter B. FileInputStream C. ObjectInputStream D. InputStreamReader 答案:D 解析:Java 的 IO 操作中有面向字节(Byte)和面向字符(Character)两种...
  • 下面哪个不属于Java标准输入输出 ASystem.in BSystem.out CSystem.stream DSystem.err (2)单选题 下面哪个属于面向字符的输入 ABufferedWriter BFileInputStream CObjectInputStream ...
  • 关于字符编码,你所需要知道的

    千次阅读 2013-11-27 15:01:53
    说到字符编码,不得说ASCII码的简史。计算机一开始发明的时候是用来解决数字计算的问题,后来人们发现,计算机还可以做更多的事,例如文本处理。但由于计算机只识“数”,因此人们必须告诉计算机哪个数字来代表...
  • 字符编码

    千次阅读 2012-11-07 15:41:02
    字符编码(Character encoding)、字集码是把字符集中的字符编码为指定集合中某一对象(例如:比特模式、自然数序列、8位元组或者电脉冲),以便文本在计算机中存储和通过通信网络的传递。常见的例子包括将拉丁字母...
  • 字符编码、字符存储、字符转换及工程中字符的使用   版本控制 版本 时间(北京时间) 作者 备注 V1.0 2016-05-13 施小丰 创建本文、第七章工程总结尚未完成 ...
  • 字符集和字符编码

    千次阅读 2017-03-18 12:44:47
    另外,还存在着一些控制字符,通常是可打印(可见)的,有特定用途,以及emoji之类特殊的符号。 字符字符集(英语:character set)指的是指定若干字符组成的一个集合,通常这个集合具有一定的规模和合理性...
  • 字节流继承于InputStream、OutputStream,字符流继承于Reader、Writer
  • IO系统详解(转)

    千次阅读 2016-05-24 22:13:25
    首先声明,这是我转载一位大牛的IO流详解,写的是十分的请楚有条理,必须转载学习一波。...Java 流在处理上分为字符流和字节流。字符流处理的单元为 2 个字节的 Unicode 字符,分别操作字符、字符数组或字符串,而字节
  • 小结字符集及字符编码问题

    千次阅读 2014-10-25 17:24:02
    字符编码问题一直深深困扰着我~无论是网页还是数据库抑或是单纯的文件字符流,总有各种奇怪的编码问题。之所以称之为奇怪其实主要还是因为我对于编码的知识了解太浅。近来深刻觉醒编码问题非解决不行,故将所阅读的...
  • Java中的流有字节流和字符流两大类,而每一种流都有对应的输入和输出流; 1、字节流 1.1字节输入流-主要是:FileInputStream 1.2字节输出流-主要是:FileOutputStream 2、字符流 2.1字符输入流-主要是:FileRea
  • 首先词法分析输入字符流,得到单词序列(本质上也是字符流,只不过进行了处理)。然后 句型分析 是输入单词序列,识别它们在 语法上是否正确 ,这是语法分析的核心部分。课本上一律采用 从左至右 的分析方法。句型...
  • Java IO详尽解析

    千次阅读 2016-03-07 17:21:18
    流的概念和作用 学习Java IO,不得提到的就是JavaIO流。 流是一组有顺序的,有起点和终点的字节集合,是对数据传输的总称或抽象。即数据在两设备间的传输称为流,流的本质是数据传输,...字符流的由来: 因为数据
  • Java IO之PrintStream分析

    万次阅读 2018-09-07 09:01:37
    的一种,所以属于字节流体系中(与PrintStream相似的流PrintWriter继承于Writer,属于字符流体系中),为其他的输出流添加功能.使它们能够方便打印各种数据值的表示形式.此外,值得注意的是: 与其他流不同的是,...
  • JAVA IO详解

    千次阅读 2014-05-08 14:31:53
    一、流的概念和作用。 流是一种有顺序的,有起点和终点的字节集合,是对数据传输的总成或抽象。即数据在两设备之间的传输称之为流,流的本质是数据传输,...字符流的由来:因为数据编码的不同,而有了对字符进行高效

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 115,449
精华内容 46,179
关键字:

下面哪些不属于字符流