java笔记--IO包中的其他类

2018-11-21  本文已影响0人  吃饱喝足搬代码丶
打印流:PrintWriter,PrintStream--可以直接操作输入流和文件。

PrintWriter:字符打印流。
构造函数:
1,字符串路经。
2,File对象。
3,字符输出流。
4,字节输出流。
PrintStream:提供了打印方法可以对多种数据类型值进行打印,并保持数据的表现形式,不抛IOException。

public static void main(String[] args) throws IOException {

        /*
         * PrintStream:
         * 1,提供了打印方法可以对多种数据类型值进行打印。并保持数据的表示形式。 
         * 2,它不抛IOException.
         * 
         * 构造函数,接收三种类型的值:
         * 1,字符串路径。
         * 2,File对象。
         * 3,字节输出流。
         */
        
        PrintStream out = new PrintStream("print.txt");
        
//      int by = read();
//      write(by);
        
//      out.write(610);//只写最低8位,
        
        out.print(97);//将97先变成字符保持原样将数据打印到目的地。
        
        out.close();
    }
运行:

SequenceInputStream:序列流--对多个流进行合并。

public class SequenceInputStreamDemo {
    public static void main(String[] args) throws IOException {

        
        /*
         * 需求:将1.txt 2.txt 3.txt文件中的数据合并到一个文件中。
         */
        
//      Vector<FileInputStream> v = new Vector<FileInputStream>();      
//      v.add(new FileInputStream("1.txt"));
//      v.add(new FileInputStream("2.txt"));
//      v.add(new FileInputStream("3.txt"));
//      Enumeration<FileInputStream> en = v.elements();
        
        ArrayList<FileInputStream> al = new ArrayList<FileInputStream>();
        for(int x=1; x<=3; x++){
            al.add(new FileInputStream(x+".txt"));
        }
        
        Enumeration<FileInputStream> en = Collections.enumeration(al);
        
        
        
        /*
        final Iterator<FileInputStream> it = al.iterator();
        Enumeration<FileInputStream> en = new Enumeration<FileInputStream>(){

            @Override
            public boolean hasMoreElements() {
                
                return it.hasNext();
            }

            @Override
            public FileInputStream nextElement() {
                
                return it.next();
            }
            
        };*/
        
        SequenceInputStream sis = new SequenceInputStream(en);
        
        FileOutputStream fos = new FileOutputStream("1234.txt");
        
        byte[] buf = new byte[1024];
        
        int len = 0;
        
        while((len=sis.read(buf))!=-1){
            fos.write(buf,0,len);
        }
        
        fos.close();
        sis.close();
        
    }
}
运行:

切割文件:

public class SplitFileDemo {

    private static final int SIZE = 1024 * 1024;

    public static void main(String[] args) throws Exception {

        File file = new File("c:\\a.mp3");

        splitFile_2(file);
    }

    private static void splitFile_2(File file) throws IOException {

        // 用读取流关联源文件。
        FileInputStream fis = new FileInputStream(file);

        // 定义一个1M的缓冲区。
        byte[] buf = new byte[SIZE];

        // 创建目的。
        FileOutputStream fos = null;

        int len = 0;
        int count = 1;
        
        
        /*
         * 切割文件时,必须记录住被切割文件的名称,以及切割出来碎片文件的个数。 以方便于合并。
         * 这个信息为了进行描述,使用键值对的方式。用到了properties对象
         * 
         */
        Properties prop  = new Properties();
        
    

        File dir = new File("c:\\partfiles");
        if (!dir.exists())
            dir.mkdirs();

        while ((len = fis.read(buf)) != -1) {

            fos = new FileOutputStream(new File(dir, (count++) + ".part"));
            fos.write(buf, 0, len);
            fos.close();
        }
        
        //将被切割文件的信息保存到prop集合中。
        prop.setProperty("partcount", count+"");
        prop.setProperty("filename", file.getName());
        
        
        
        fos = new FileOutputStream(new File(dir,count+".properties"));
        
        //将prop集合中的数据存储到文件中。 
        prop.store(fos, "save file info");

        fos.close();
        fis.close();

    }

    public static void splitFile(File file) throws IOException {

        // 用读取流关联源文件。
        FileInputStream fis = new FileInputStream(file);

        // 定义一个1M的缓冲区。
        byte[] buf = new byte[SIZE];

        // 创建目的。
        FileOutputStream fos = null;

        int len = 0;
        int count = 1;

        File dir = new File("c:\\partfiles");
        if (!dir.exists())
            dir.mkdirs();

        while ((len = fis.read(buf)) != -1) {

            fos = new FileOutputStream(new File(dir, (count++) + ".part"));
            fos.write(buf, 0, len);
        }

        fos.close();
        fis.close();

    }
}
运行:

合并文件:

public class MergeFile {
    public static void main(String[] args) throws IOException {

        File dir = new File("c:\\partfiles");
        
        mergeFile_2(dir);
    }
    
    public static void mergeFile_2(File dir) throws IOException {
        
        /*
         * 获取指定目录下的配置文件对象。
         */
        File[] files = dir.listFiles(new SuffixFilter(".properties"));
        
        if(files.length!=1)
            throw new RuntimeException(dir+",该目录下没有properties扩展名的文件或者不唯一");
        //记录配置文件对象。
        File confile = files[0];
        
        
        
        //获取该文件中的信息================================================。
        
        Properties prop = new Properties();
        FileInputStream fis = new FileInputStream(confile);
        
        prop.load(fis);
        
        String filename = prop.getProperty("filename");     
        int count = Integer.parseInt(prop.getProperty("partcount"));
        
        
        
        
        //获取该目录下的所有碎片文件。 ==============================================
        File[] partFiles = dir.listFiles(new SuffixFilter(".part"));
        
        if(partFiles.length!=(count-1)){
            throw new RuntimeException(" 碎片文件不符合要求,个数不对!应该"+count+"个");
        }
        
        
        
        //将碎片文件和流对象关联 并存储到集合中。 
        ArrayList<FileInputStream> al = new ArrayList<FileInputStream>();
        for(int x=0; x<partFiles.length; x++){
            
            al.add(new FileInputStream(partFiles[x]));
        }
        
        
        
        //将多个流合并成一个序列流。 
        Enumeration<FileInputStream> en = Collections.enumeration(al);
        SequenceInputStream sis = new SequenceInputStream(en);
        
        FileOutputStream fos = new FileOutputStream(new File(dir,filename));
        
        byte[] buf = new byte[1024];
        
        int len = 0;
        while((len=sis.read(buf))!=-1){
            fos.write(buf,0,len);
        }
        
        fos.close();
        sis.close();
        
        
        
        
        
        
    }

    public static void mergeFile(File dir) throws IOException{
        
        
        ArrayList<FileInputStream> al = new ArrayList<FileInputStream>();
        
        for(int x=1; x<=3 ;x++){
            al.add(new FileInputStream(new File(dir,x+".part")));
        }
        
        Enumeration<FileInputStream> en = Collections.enumeration(al);
        SequenceInputStream sis = new SequenceInputStream(en);
        
        FileOutputStream fos = new FileOutputStream(new File(dir,"2.mp3"));
        
        byte[] buf = new byte[1024];
        
        int len = 0;
        while((len=sis.read(buf))!=-1){
            fos.write(buf,0,len);
        }
        
        fos.close();
        sis.close();
        
    }
}
运行:

ObjectInputStream与ObjectOutputStream:操作对象,但是被操作的对象需要实现Serializable。
Serializable:用于给被序列化的类加入ID号,用于判断类和对象是否是同一个版本。

public class Person implements Serializable/*标记接口*/ {

    private static final long serialVersionUID=9527l;//Serializable使得类每次改动都会生成不同的序列号,所以会发生InvalidClassException.这里给固定一个序列,解决问题。
    private String name;//可改动变量修饰符试一下是否抛出InvalidClassException.
    private int age;
    
    
    public Person(String name, int age) {
        super();
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }
    
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
}
public static void main(String[] args) throws IOException, ClassNotFoundException {
            
//      writeObj();
        readObj();
    }

    public static void readObj() throws IOException, ClassNotFoundException {
        
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("obj.object"));
        //对象的反序列化。 
        Person p = (Person)ois.readObject();
        
        System.out.println(p.getName()+":"+p.getAge());
        
        ois.close();
        
    }

    public static void writeObj() throws IOException, IOException {
        
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("obj.object"));
        //对象序列化。  被序列化的对象必须实现Serializable接口。 
        oos.writeObject(new Person("小强",30));
        
        oos.close();

    }
}
运行:

transient:非静态数据不想序列化可使用这个关键字修饰。
writeObject:对象的类、类的签名,以及类及其所有超类型的非瞬态和非静态字段的值都可被写入。

public class Person implements Serializable/*标记接口*/ {

    /**
     * transient:非静态数据不想被序列化可以使用这个关键字修饰。
     */
    private static final long serialVersionUID = 9527l;
    private transient String name;
    private static int age;//静态不可被写入
    
    
    public Person(String name, int age) {
        super();
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }
    
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }   
}
public static void main(String[] args) throws IOException, ClassNotFoundException {
            
//      writeObj();
        readObj();
    }

    public static void readObj() throws IOException, ClassNotFoundException {
        
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("obj.object"));
        //对象的反序列化。 
        Person p = (Person)ois.readObject();
        
        System.out.println(p.getName()+":"+p.getAge());
        
        ois.close();
        
    }

    public static void writeObj() throws IOException, IOException {
        
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("obj.object"));
        //对象序列化。  被序列化的对象必须实现Serializable接口。 
        oos.writeObject(new Person("小强",30));
        
        oos.close();

    }
}
运行:

RandomAccessFile:随机访问文件,自身具备读写的方法。通过skipBytes(int x),seek(int x)来达到随机访问。
因为可以随机写入,所以写文件可用多线程同时进行读写操作。

public class RandomAccessFileDemo {

    public static void main(String[] args) throws IOException {
        /*
        RandomAccessFile:
            1,该对象既能读,又能写
            2,该对象内部维护了一个byte数组,并通过指针可以操作数组中的元素
            3,可以通过getFilePointer方法获取指针位置,通过seek方法设置指针位置
            4,其实该对象就是将字节输入流和输出流进行了封装。
            5,该对象的源或者目的只能是文件。可通过构造函数看出。
            */
        
//      writeFile();
        readFile();
    }
    
    public static void readFile() throws IOException {
        
        RandomAccessFile raf=new RandomAccessFile("ranacc.txt","r");
        
        byte[] buf=new byte[4];
        raf.read(buf);
        
        String name=new String(buf);
        int age=raf.readInt();
        
        System.out.println("name="+name);
        System.out.println("age="+age);
        raf.close();
    }

    //使用RandomAccessFile对象写入一些人员信息,比如姓名,年龄
    public static void writeFile() throws IOException {
        
//      如果文件不存在,则创建,存在则不创建
        RandomAccessFile raf=new RandomAccessFile("ranacc.txt","rw");//rw:打开以便读取和写入,若文件不存在,尝试创建
        
        raf.write("张三".getBytes());
        raf.writeInt(97);
        raf.write("小强".getBytes());
        raf.writeInt(99);
        
        raf.close();
    }
}
运行:
public static void randomWrite() throws IOException {
        RandomAccessFile raf=new RandomAccessFile("ranacc.txt","rw");
        
        //往指定位置写入数据
        raf.seek(3*8);
        
        raf.write("哈哈".getBytes());
        raf.writeInt(108);
        
        raf.close();
    }

    public static void readFile() throws IOException {
        
        RandomAccessFile raf=new RandomAccessFile("ranacc.txt","r");
        
        //通过seek设置指针的位置
        raf.seek(1*8);//随机读取,只要指定指针位置即可
        
        byte[] buf=new byte[4];
        raf.read(buf);
        
        String name=new String(buf);
        
        int age=raf.readInt();
        
        System.out.println("name="+name);
        System.out.println("age="+age);
        
        System.out.println("pos="+raf.getFilePointer());
        raf.close();
    }
运行:

PipedInputStream,PipedOutputStream:管道流,输入输出可以直接进行连接,通过结合线程使用。

public class PipedStream {

    public static void main(String[] args) throws IOException {
        
        PipedInputStream input=new PipedInputStream();
        PipedOutputStream output=new PipedOutputStream();
        
        input.connect(output);
        
        new Thread(new Input(input)).start();
        new Thread(new Output(output)).start();

    }

}

class Input implements Runnable{
    
    private PipedInputStream in;
    Input(PipedInputStream in){
        this.in = in;
    }
    public void run(){
        
        try {
            byte[] buf = new byte[1024];
            int len = in.read(buf);
            
            String s = new String(buf,0,len);
            
            System.out.println("s="+s);
            in.close();
        } catch (Exception e) {
        }
        
    }
}
class Output implements Runnable{
    private PipedOutputStream out;
    Output(PipedOutputStream out){
        this.out = out;
    }
    public void run(){
        
        try {
            Thread.sleep(5000);
            out.write("hi,管道来了!".getBytes());
        } catch (Exception e) {
        }
    }
}
运行:

DataInputStream,DataOutputStream:操作基本数据类型。

public class DataStreamDemo {

    public static void main(String[] args) throws IOException {
        
        writeData();
        readData();
    }

    public static void readData() throws IOException {
        
        DataInputStream dis=new DataInputStream(new FileInputStream("data.txt"));
        
        String str=dis.readUTF();
        
        System.out.println(str);
    }

    public static void writeData() throws IOException {
        
        DataOutputStream dos=new DataOutputStream(new FileOutputStream("data.txt"));
        
        dos.writeUTF("你好");
        
        dos.close();
    }
}
运行:

ByteArrayReader,CharArrayWrite:操作字节数组。
CharArrayReader,CharArrayWrite:操作字符数组。
StringReader,StringWriter:操作字符串。

public class ByteArrayStreamDemo {

    public static void main(String[] args) {
        
        ByteArrayInputStream bis=new ByteArrayInputStream("abcdef".getBytes());
        
        ByteArrayOutputStream bos=new ByteArrayOutputStream();
        
        int ch=0;
        
        while((ch=bis.read())!=-1){
            bos.write(ch);
        }
        System.out.println(bos.toString());
    }

}
运行:

字符编码:字符流的出现是为了方便操作字符,更重要的是加入了编码转换--通过子类转换流完成--InputStreamReader,OutputStreamWriter。在两个对象进行构造的时候可以加入字符集。

public class EncodeDemo {

    public static void main(String[] args) throws IOException {
        /*
        字符串 -->字节数组:编码。
        字节数组 -->字符串:解码。
        */
        
        String str="谢谢";
        
        byte[] buf=str.getBytes("gbk");
        
        String s1=new String(buf,"UTF-8");
        
        System.out.println("s1="+s1);
        
        byte[] buf2=s1.getBytes("UTF-8");//获取源字节。
        
        printBytes(buf2);
        
        String s2=new String(buf2,"GBK");
        
        System.out.println("s2="+s2);
        
        encodeDemo(str);
    }

    public static void encodeDemo(String str) throws UnsupportedEncodingException {
        //编码
        byte[] buf=str.getBytes("UTF-8");
        
        printBytes(buf);
        
        //解码
        String s1=new String(buf,"UTF-8");
        
        System.out.println("s1="+s1);
    }

    public static void printBytes(byte[] buf) {
        for(byte b:buf){
            System.out.print(b+" ");
        }
        
    }
}
运行:

联通问题(utf-8修改版字节表现形式):


新建文本
保存后再打开
原因:保存时,默认系统编码方式,打开时以utf-8的方式打开。

验证:

public class LianTong {

    public static void main(String[] args) throws IOException {
        String str="联通";
        
        byte[] buf=str.getBytes("gbk");
        
        for(byte b:buf){
            System.out.println(Integer.toBinaryString(b&255));
        }

    }
}
运行:

截取字符:

public class Test {

    public static void main(String[] args) throws IOException {
        
        String str="ab你好cd谢谢";
//      str="ab琲琲cd琲琲";
        
        /*int len=str.getBytes("gbk").length;
        for(int x=0;x<len;x++){
            System.out.println("截取"+(x+1)+"个字节结果是:"+cutStringByByte(str,x+1));
        }*/
        
        int len=str.getBytes("utf-8").length;
        for(int x=0;x<len;x++){
            System.out.println("截取"+(x+1)+"个字节结果"+cutStringByU8Byte(str,x+1));
        }
        
        /*String str="琲";
        byte[] buf=str.getBytes("gbk");
        for(byte b:buf){
            System.out.println(b);
        }*/
    }
    /*
    在java中,字符串"abcd"与字符串"ab你好"的长度是一样的,都是四个字符。
    但对应的字节数不同,一个汉字占两个字节。
    定义一个方法,按照最大的字节数来取子串。
    如:对于"ab你好",如果取三个字节,那么子串就是ab与"你"字的半个,没那
    么半个就要舍弃。如果去四个字节就是"ab你",取五个字节还是"ab你"。
    */

    public static String cutStringByU8Byte(String str, int len) throws IOException {
        
        byte[] buf =str.getBytes("utf-8");
        
        int count=0;
        for(int x=len-1;x>=0;x--){
            if(buf[x]<0)
                count++;
            else
                break;
        }
        if(count%3==0)
            return new String(buf,0,len,"utf-8");
        else if(count%3==1)
            return new String(buf,0,len-1,"utf-8");
        else
            return new String(buf,0,len-2,"utf-8");
    }

    public static String cutStringByByte(String str, int len) throws IOException {
        
        byte[] buf=str.getBytes("gbk");
        
        int count=0;
        for(int x=len-1;x>0;x--){
            if(buf[x]<0)
                count++;
            else
                break;
        }
        if(count%2==0)
            return new String(buf,0,len,"gbk");
        else
            return new String(buf,0,len-1,"gbk");
    }
}
运行:
上一篇下一篇

猜你喜欢

热点阅读