Java java지도 시간 Java I/O 입력 및 출력 스트림에 대한 자세한 소개

Java I/O 입력 및 출력 스트림에 대한 자세한 소개

Jul 20, 2017 pm 02:23 PM
java 입력하다 산출

Java流的分类

按流向分:

输入流: 程序可以从中读取数据的流。

输出流: 程序能向其中写入数据的流。

按数据传输单位分:

字节流: 以字节为单位传输数据的流

字符流: 以字符为单位传输数据的流

按功能分:

节点流: 用于直接操作目标设备的流

处理流: 是对一个已存在的流的链接和封装,通过对数据进行处理为程序提供功能强大、灵活的读写功能。

1、编码问题

String s = "哈喽ABC";byte[] bytes1 = s.getBytes();//转换成字节序列用的是项目默认的编码utf-8for (byte b : bytes1) {//把字节(转换成了int)以16进制的方式显示//把byte转换成int  其实就是把后8位前面添24个0变成32位变成4个字节//前24个0没有意义,所以位与上0xff是把前24个0去掉  只留下后8位System.out.print(Integer.toHexString(b&0xff)+"  ");//输出e5  93  88  e5  96  bd  41  42  43          }
        System.out.println();byte[] bytes2 = s.getBytes("gbk");for (byte b : bytes2) {
            System.out.print(Integer.toHexString(b&0xff)+" ");//输出b9 fe e0 b6 41 42 43         }//结论:gbk编码中文占用2个字节,英文占用1个字节;utf-8编码中文占用3个字节,英文占用1个字节        System.out.println();//java是双字节编码 utf-16bebyte[] bytes3 = s.getBytes("utf-16be");for (byte b : bytes3) {
            System.out.print(Integer.toHexString(b&0xff)+" ");
        }//结论:utf-16be中文占用2个字节,英文占用2个字节        
        System.out.println();/* * 当你的字节序列是某种编码时,这个时候想把字节序列变成字符串,
         * 也需要用这种编码方式,否则会出现乱码         */String str1 = new String(bytes3);
        System.out.println(str1);//输出:T�U� A B CString str2 = new String(bytes3,"utf-16be");
        System.out.println(str2);//输出:哈喽ABC/* * 文本文件 就是字节序列
         * 可以是任意编码的字节序列
         * 如果我们在中文机器上直接创建文本文件,那么该文本文件只认识ANSI编码
         * 联通、联这是一种巧合,他们正好符合了utf-8编码的规则         */
로그인 후 복사

2、File类的使用

java.io.File类用于表示文件(目录)

File类只用于表示文件(目录)的信息(名称、大小等),不能用于文件内容的访问

  (1)File类的常用api

File file = new File("e:\\javaio");
        File file2 = new File("e:"+File.separator+"javaio");
        System.out.println(file.exists());if(!file.exists())
            file.mkdir();elsefile.delete();//是否是一个目录 如果是目录返回true,如果不是目录or目录不存在返回的是false        System.out.println(file.isDirectory());//是否是一个文件        System.out.println(file.isFile());
        
        File file3 = new File("e:"+File.separator+"javaio"+File.separator+"test.txt");//File file3 = new File("e:\\javaid","test.txt");if(!file3.exists())try {
                file3.createNewFile();
            } catch (IOException e) {// TODO Auto-generated catch block                e.printStackTrace();
            }elsefile3.delete();
        
        System.out.println(file);//file.toString()的内容//e:\javaioSystem.out.println(file.getAbsolutePath());//e:\javaioSystem.out.println(file.getName());//javaioSystem.out.println(file3.getName());//test.txtSystem.out.println(file.getParent());//e:\System.out.println(file3.getParent());//e:\javaioSystem.out.println(file.getParentFile().getAbsolutePath());//e:\
로그인 후 복사

  (2)遍历目录

//列出File的一些常用的操作比如过滤、遍历等操作public class FileUtils {/**
 * 列出指定目录下(包括其子目录)的所有文件 */public static void listDirectory(File dir){if(!dir.exists()){throw new IllegalArgumentException("目录"+dir+"不存在");
        }if(!dir.isDirectory()){throw new IllegalArgumentException(dir+"不是目录");
        }//返回的是字符串数组 直接子的名称,不包含子目录下的内容String[] filenames = dir.list();for (String string : filenames) {
            System.out.println(dir+"\\"+string);
        }//如果要遍历子目录下的内容就需要构造成File对象做递归操作,File提供了直接返回File对象的APIFile[] files = dir.listFiles();//返回的是直接子目录(文件)的抽象for (File file : files) {
            System.out.println(file);
        }if(files!=null&&files.length>0)for (File file : files) {if(file.isDirectory()){//递归                    listDirectory(file);
                }else{
                    System.out.println(file);
                }
            }
    }
}
로그인 후 복사

3、RandomAccessFile  java提供的对文件内容的访问,既可以读文件,也可以写文件。

RandomAccessFile 支持随机访问文件,可以访问文件的任意位置

(1)java文件模型

在硬盘上的文件是byte byte byte存储的,是数据的集合

(2)打开文件

有两种模式“rw”(读写)“r”(只读)

RandomAccessFile  raf = new RandomAccessFile (file,"rw");

文件指针,打开文件时指针在开头pointer=0;

(3)写方法

raf.write(int)--->只写一个字节(后8位),同事指针指向下一个位置,准备再次写入

(4)读方法

int b = raf.read()--->读一个字节

(5)文件读写完成以后一定要关闭。

File demo = new File("demo");if(!demo.exists())
            file.createNewFile();
        RandomAccessFile raf = new RandomAccessFile(file, "rw");//指针的位置        System.out.println(raf.getFilePointer());
        
        raf.write('A');//只写了一个字节        System.out.println(raf.getFilePointer());
        raf.write('B');        int i = 0x7fffffff;//用write方法每次只能写一个字节,如果要把i写进去就得写4次raf.write(i>>>24);//高8位raf.write(i>>>16);
        raf.write(i>>>8);
        raf.write(i);
        System.out.println(raf.getFilePointer());        //可以直接写一个int        raf.write(i);
        
        String s1 = "中";byte[] gbk = s1.getBytes("gbk");
        raf.write(gbk);
        System.out.println(raf.length());        //读文件,必须把指针移到头部raf.seek(0);//一次性读取,把文件中的内容都读到字节数组中byte[] buf = new byte[(int)raf.length()];
        raf.read(buf);
        System.out.println(Arrays.toString(buf));
        String s2 = new String(buf);for (byte b : buf) {
            System.out.print(Integer.toHexString(b&0xff)+" ");
        }
        raf.close();
로그인 후 복사

 4、IO流(输入流、输出流)

字节流、字符流

(1)字节流

1)InputStream、OutputStream

InputStream抽象了应用程序读取数据的方式

OutputStream抽象了应用程序写出数据的方式

2)EOF = End 读到-1就读到结尾

3)输入流基本方法

int b=in.read();读取一个字节无符号填充到int低8位。-1是EOF

in.read(byte[] buf) 读取数据填充到字节数组buf

in.read(byte[] buf,int start, int size)读取数据到字节数组buf,从buf的start位置开始存放size长度的数据

4)输出流基本方法

out.write(int b) 写出一个byte到流,b的低8位

out.write(byte[] buf) 将buf字节数组都写入到流

out.write(bytep[] buf, int start ,int size) 字节数组buf从start位置开始写size长度的字节到流

5)FileInputStream--->具体实现了在文件上读取数据

public class IOUtil {/** * 读取指定文件内容,按照16进制输出到控制台
     * 并且每输出10个byte换行
     * @param fileName     */public static void printHex(String fileName)throws IOException{//把文件作为字节流进行操作FileInputStream in = new FileInputStream(fileName);int b;int i = 1;while((b=in.read())!=-1){if(b<=0xf){//单位数前面补0System.out.print("0");
            }
            System.out.print(Integer.toHexString(b)+" ");//将整型b转换为16进制表示的字符串if(i++%10==0){
                System.out.println();
            }
        }
        in.close();
    }public static void printHexByByteArray(String fileName)throws IOException{
        FileInputStream in  = new FileInputStream(fileName);byte[] buf = new byte[20*1024];/* * 从in中批量读取字节,放入到buf这个字节数组中,
         * 从第0个位置开始放,最多放buf.length个
         * 返回的是读到的字节的个数         */int bytes = in.read(buf,0,buf.length);//一次性读完,说明字节数组足够大int j = 1;for (int i = 0; i < bytes; i++) {if(buf[i]<=0xf){
                System.out.println("0");
            }
            System.out.println(Integer.toHexString(buf[i]&0xff)+"  ");if(j++%10==0){
                System.out.println();
            }
        }        int bytes2 = 0;while((bytes2=in.read(buf,0,buf.length))!=-1){for (int i = 0; i < bytes2; i++) {//                byte类型8位,int类型32位,//                为了避免数据转换错误,通过&0xff将高24位清0System.out.println(Integer.toHexString(buf[i]&0xff)+"  ");if(j++%10==0){
                    System.out.println();
                }
            }
        }
로그인 후 복사

6)FileOutputStream 实现了向文件中写出byte数据的方法

/** * 文件拷贝
     * @param srcFile
     * @param destFile
     * @throws IOException     */public static void copyFile(File srcFile,File destFile)throws IOException{if(!srcFile.exists()){throw new IllegalArgumentException("文件"+srcFile+"不存在");
        }if(!srcFile.isFile()){throw new IllegalAccessError(srcFile+"不是文件");
        }
        FileInputStream in = new FileInputStream(srcFile);
        FileOutputStream out = new FileOutputStream(destFile);byte[] buf = new byte[8*1024];int b;while((b=in.read(buf,0,buf.length))!=-1){
            out.write(buf,0,b);
            out.flush();//最好加上        }
        in.close();
        out.close();
        
    }
로그인 후 복사

7)DataOutputStream和DataInputStream

对“流”功能的扩展,可以更加方便的读取int,long,字符等类型数据

DataOutputStream

  writeInt()/writeDouble()/writeUTF()

String file = "dos.dat";
        DataOutputStream dos = new DataOutputStream(new FileOutputStream(file));
        dos.writeInt(20);
        dos.writeInt(-10);
        dos.writeLong(10l);
        dos.writeDouble(10.3);//采用utf-8编码写出dos.writeUTF("中国");//采用utf-16be编码写出dos.writeChars("中国");
        
        dos.close();
        IOUtil.printHex(file);
로그인 후 복사

DataInputStream

String file2 = "dos.dat";
        IOUtil.printHex(file2);
        DataInputStream dis = new DataInputStream(new FileInputStream(file2));
        System.out.println();int i = dis.readInt();
        System.out.println(i);
        i = dis.readInt();
        System.out.println(i);long l = dis.readLong();
        System.out.println(l);double d = dis.readDouble();
        System.out.println(d);
        String s = dis.readUTF();
        System.out.println(s);
        dis.close();
로그인 후 복사

8)BufferedInputStream和BufferedOutputStream

这两个流类为IO提供了带缓冲区的操作,一般打开文件进行写入或读取操作时,都会加上缓冲,这种流模式提高了IO的性能

从应用程序中把输入放入文件,相当于将一缸水倒入到另一个缸中:

FileOutputStream--->write()方法相当于一滴一滴地把水“转移”过去

DataOutputStream--->writeXxx()方法相当于一瓢一瓢把水转移过去

BufferedOutputStream--->write()方法更方便,相当于一瓢一瓢先放入桶中,再从桶中倒入到另一个缸中

/** * 文件拷贝
     * @param srcFile
     * @param destFile
     * @throws IOException     */public static void copyFile(File srcFile,File destFile)throws IOException{if(!srcFile.exists()){throw new IllegalArgumentException("文件"+srcFile+"不存在");
        }if(!srcFile.isFile()){throw new IllegalAccessError(srcFile+"不是文件");
        }
        FileInputStream in = new FileInputStream(srcFile);
        FileOutputStream out = new FileOutputStream(destFile);byte[] buf = new byte[8*1024];int b;while((b=in.read(buf,0,buf.length))!=-1){
            out.write(buf,0,b);
            out.flush();//最好加上        }
        in.close();
        out.close();
        
    }    /** * 进行文件拷贝,利用DataInputStream和DataOutputStream
     * @param srcFile
     * @param destFile
     * @throws IOException     */public static void copyFileByData(File srcFile,File destFile)throws IOException{if(!srcFile.exists()){throw new IllegalArgumentException("文件"+srcFile+"不存在");
        }if(!srcFile.isFile()){throw new IllegalArgumentException(srcFile+"不是文件");
        }
        DataInputStream bis = new DataInputStream(new FileInputStream(srcFile));
        DataOutputStream bos = new DataOutputStream(new FileOutputStream(destFile));byte[] buf = new byte[8*1024];int c;while((c=bis.read(buf,0,buf.length))!=-1){
            bos.write(buf,0,c);
            bos.flush();
        }
        bis.close();
        bos.close();
    }/** * 进行文件拷贝,利用带缓冲的字节流
     * @param srcFile
     * @param destFile
     * @throws IOException     */public static void copyFileByBuffer(File srcFile,File destFile)throws IOException{if(!srcFile.exists()){throw new IllegalArgumentException("文件"+srcFile+"不存在");
        }if(!srcFile.isFile()){throw new IllegalArgumentException(srcFile+"不是文件");
        }
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream(srcFile));
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(destFile));byte[] buf = new byte[8*1024];int c;while((c=bis.read(buf,0,buf.length))!=-1){
            bos.write(buf,0,c);
            bos.flush();
        }
        bis.close();
        bos.close();
    }
로그인 후 복사

(2)字符流

Reader   Writer

字符的处理,一次处理一个字符

字符的底层仍然是基本的字节序列

字符流的基本实现

  InputStreamReader 完成byte流解析为char流,按照编码解析

  OutputStreamWriter 提供char流到byte流,按照编码处理

InputStreamReader isr = new InputStreamReader(new FileInputStream("out.dat"),"gbk");//默认项目的编码,操作的时候要写文件本身的编码FileOutputStream out = new FileOutputStream("out2.dat");
        OutputStreamWriter osw = new OutputStreamWriter(out,"utf-8");//        int c;//        while((c=isr.read())!=-1){//            System.out.print((char)c);//        }char[] buffer = new char[8*1024];int c;//批量读取,放入buffer这个字符数组,从第0个位置开始放置,最多放buffer.length//返回的是读到的字符的个数while((c=isr.read(buffer, 0, buffer.length))!=-1){//需要把这个字符数组构造成字符串String s = new String(buffer,0,c);
            System.out.print(s);
            osw.write(buffer,0,c);
            osw.flush();
        }
        isr.close();
        osw.close();
로그인 후 복사

FileReader、FileWriter

FileReader fr = new FileReader("out.dat");
        FileWriter fw = new FileWriter("out3.dat");//        FileWriter fw = new FileWriter("out3.dat");char[] buffer = new char[2056];int c;while((c=fr.read(buffer ,0,buffer.length))!=-1){
            fw.write(buffer,0,c);
            fw.flush();
        }
        fr.close();
        fw.close();
로그인 후 복사

字符流过滤器

BufferedReader --->readLine  一次读一行

BufferedWriter/PrinterWriter  --->写一行

//对文件进行读写操作BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("out.dat"),"gbk"));
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("out4.dat")));
        PrintWriter pw = new PrintWriter("out5.dat");//PrintWriter pw2 = new PrintWriter(outputStream,boolean autoFlush);        String line;while((line=br.readLine())!=null){
            System.out.println(line);//一次读一行,并不能识别换行            bw.write(line);//单独写出换行操作bw.newLine();//换行操作            bw.flush();
            pw.println(line);
            pw.flush();
        }
        br.close();
        bw.close();
        pw.close();
로그인 후 복사

5、对象的序列化,反序列化

(1)对象的序列化,就是将Object转换成byte序列,反之叫对象的反序列化

(2)序列化流(ObjectOutputStream),是过滤流----writeObject

   反序列化流(ObjectInputStream)----readObject

(3)序列化接口(Serializable)

  对象必须实现序列化接口,才能进行序列化,否则将出现异常

  这个接口,没有任何方法,只是一个标准

String file = "stu.dat";//1.对象的序列化ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(file));
        Student stu = new Student("10001","张三",20);
        oos.writeObject(stu);
        oos.flush();
        oos.close();        //2.对象的反序列化ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file));
        Student stu1 = (Student)ois.readObject();
        System.out.println(stu1);
        ois.close();
로그인 후 복사

(4)transient关键字

  private void writeObject(java.io.ObjectOutputStream s)throws java.io.IOException

  private void readObject(java.io.ObjectInputStream s)
  throws java.io.IOException, ClassNotFoundException

分析ArrayList源码中序列化和反序列化的问题

public class Student implements Serializable{private String stuno;private String stuname;private transient int stuage;//加了transient关键字,则该元素不会进行jvm默认的序列化,也可以自己完成这个元素的序列化public Student(){}    public Student(String stuno, String stuname, int stuage) {super();this.stuno = stuno;this.stuname = stuname;this.stuage = stuage;
    }public String getStuno() {return stuno;
    }public void setStuno(String stuno) {this.stuno = stuno;
    }public String getStuname() {return stuname;
    }public void setStuname(String stuname) {this.stuname = stuname;
    }public int getStuage() {return stuage;
    }public void setStuage(int stuage) {this.stuage = stuage;
    }
    @Overridepublic String toString() {return "Student [stuno=" + stuno + ", stuname=" + stuname + ", stuage="
                + stuage + "]";
    }private void writeObject(java.io.ObjectOutputStream s)throws java.io.IOException{
        s.defaultWriteObject();//把jvm能默认序列化的元素进行序列化操作s.writeInt(stuage);//自己完成student的序列化(stuage用transient修饰了,也可以自己序列化)    }private void readObject(java.io.ObjectInputStream s)throws java.io.IOException, ClassNotFoundException{
        s.defaultReadObject();//把jvm能默认反序列化的元素进行反序列化操作this.stuage = s.readInt();//自己完成stuage的反序列化操作    }
}
로그인 후 복사

(5)序列化中 子类和父类构造函数的调用问题

一个类实现了序列化接口,那么其子类都可以进行序列化

对子类对象进行反序列化操作时,如果其父类没有实现序列化接口那么其父类的构造函数就会被调用,否则就不会被调用。

위 내용은 Java I/O 입력 및 출력 스트림에 대한 자세한 소개의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.

핫 AI 도구

Undresser.AI Undress

Undresser.AI Undress

사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover

AI Clothes Remover

사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool

Undress AI Tool

무료로 이미지를 벗다

Clothoff.io

Clothoff.io

AI 옷 제거제

Video Face Swap

Video Face Swap

완전히 무료인 AI 얼굴 교환 도구를 사용하여 모든 비디오의 얼굴을 쉽게 바꾸세요!

뜨거운 도구

메모장++7.3.1

메모장++7.3.1

사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전

SublimeText3 중국어 버전

중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기

스튜디오 13.0.1 보내기

강력한 PHP 통합 개발 환경

드림위버 CS6

드림위버 CS6

시각적 웹 개발 도구

SublimeText3 Mac 버전

SublimeText3 Mac 버전

신 수준의 코드 편집 소프트웨어(SublimeText3)

자바의 완전수 자바의 완전수 Aug 30, 2024 pm 04:28 PM

Java의 완전수 가이드. 여기서는 정의, Java에서 완전 숫자를 확인하는 방법, 코드 구현 예제에 대해 논의합니다.

자바의 웨카 자바의 웨카 Aug 30, 2024 pm 04:28 PM

Java의 Weka 가이드. 여기에서는 소개, weka java 사용 방법, 플랫폼 유형 및 장점을 예제와 함께 설명합니다.

Java의 스미스 번호 Java의 스미스 번호 Aug 30, 2024 pm 04:28 PM

Java의 Smith Number 가이드. 여기서는 정의, Java에서 스미스 번호를 확인하는 방법에 대해 논의합니다. 코드 구현의 예.

Java Spring 인터뷰 질문 Java Spring 인터뷰 질문 Aug 30, 2024 pm 04:29 PM

이 기사에서는 가장 많이 묻는 Java Spring 면접 질문과 자세한 답변을 보관했습니다. 그래야 면접에 합격할 수 있습니다.

Java 8 Stream foreach에서 나누거나 돌아 오시겠습니까? Java 8 Stream foreach에서 나누거나 돌아 오시겠습니까? Feb 07, 2025 pm 12:09 PM

Java 8은 스트림 API를 소개하여 데이터 컬렉션을 처리하는 강력하고 표현적인 방법을 제공합니다. 그러나 스트림을 사용할 때 일반적인 질문은 다음과 같은 것입니다. 기존 루프는 조기 중단 또는 반환을 허용하지만 스트림의 Foreach 메소드는이 방법을 직접 지원하지 않습니다. 이 기사는 이유를 설명하고 스트림 처리 시스템에서 조기 종료를 구현하기위한 대체 방법을 탐색합니다. 추가 읽기 : Java Stream API 개선 스트림 foreach를 이해하십시오 Foreach 메소드는 스트림의 각 요소에서 하나의 작업을 수행하는 터미널 작동입니다. 디자인 의도입니다

Java의 날짜까지의 타임스탬프 Java의 날짜까지의 타임스탬프 Aug 30, 2024 pm 04:28 PM

Java의 TimeStamp to Date 안내. 여기서는 소개와 예제와 함께 Java에서 타임스탬프를 날짜로 변환하는 방법에 대해서도 설명합니다.

캡슐의 양을 찾기위한 Java 프로그램 캡슐의 양을 찾기위한 Java 프로그램 Feb 07, 2025 am 11:37 AM

캡슐은 3 차원 기하학적 그림이며, 양쪽 끝에 실린더와 반구로 구성됩니다. 캡슐의 부피는 실린더의 부피와 양쪽 끝에 반구의 부피를 첨가하여 계산할 수 있습니다. 이 튜토리얼은 다른 방법을 사용하여 Java에서 주어진 캡슐의 부피를 계산하는 방법에 대해 논의합니다. 캡슐 볼륨 공식 캡슐 볼륨에 대한 공식은 다음과 같습니다. 캡슐 부피 = 원통형 볼륨 2 반구 볼륨 안에, R : 반구의 반경. H : 실린더의 높이 (반구 제외). 예 1 입력하다 반경 = 5 단위 높이 = 10 단위 산출 볼륨 = 1570.8 입방 단위 설명하다 공식을 사용하여 볼륨 계산 : 부피 = π × r2 × h (4

미래를 창조하세요: 완전 초보자를 위한 Java 프로그래밍 미래를 창조하세요: 완전 초보자를 위한 Java 프로그래밍 Oct 13, 2024 pm 01:32 PM

Java는 초보자와 숙련된 개발자 모두가 배울 수 있는 인기 있는 프로그래밍 언어입니다. 이 튜토리얼은 기본 개념부터 시작하여 고급 주제를 통해 진행됩니다. Java Development Kit를 설치한 후 간단한 "Hello, World!" 프로그램을 작성하여 프로그래밍을 연습할 수 있습니다. 코드를 이해한 후 명령 프롬프트를 사용하여 프로그램을 컴파일하고 실행하면 "Hello, World!"가 콘솔에 출력됩니다. Java를 배우면 프로그래밍 여정이 시작되고, 숙달이 깊어짐에 따라 더 복잡한 애플리케이션을 만들 수 있습니다.

See all articles