Java语言基础-IO流(输入输出流) 其他

Properties集合

Map
    |--Hashtable
        |--Properties

public class Properties extends Hashtable<Object,Object>
Properties 类表示了一个持久的属性集。Properties 可保存在流中或从流中加载。属性列表中每个键及其对应值都是一个字符串。
Properties集合:
特点:
1.该集合中的键和值都是字符串类型;
2.集合中的数据可以保存到流中或者从流中获取数据;

应用场景:通常该集合用于操作以键值对存在的配置文件。

package cn.itcase.io.p2.properties;



import java.io.BufferedReader;

import java.io.File;

import java.io.FileInputStream;

import java.io.FileOutputStream;

import java.io.FileReader;

import java.io.FileWriter;

import java.io.IOException;

import java.util.Properties;

import java.util.Set;



public class PropertiesDemo {



    /**

     * @param args

     * @throws IOException

     */

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



        // propertiesDemo();

        // propertiesDemo_2();

        // propertiesDemo_3();

        // propertiesDemo_4();

        // myLoad();

        test();

    }



    // 对已有的配置文件中的信息进行修改

    /*

     * 读取文件,并将这个文件中的键值数据存储到集合中;

     * 再通过集合对数据进行修改;

     * 再通过流将修改后的数据存储到文件中。

     */

    public static void test() throws IOException {

        // 读取这个文件

        File file = new File("info.txt");



        if (!file.exists()) {

            file.createNewFile();

        }

        FileReader fr = new FileReader("info.txt");

        

        // 如果放在这里,就新创建了文件覆盖掉原先的文件,文件为空

        // FileWriter fw=new FileWriter(file);

        // 创建集合,存储配置信息

        Properties prop = new Properties();



        // 将流中的信息存储到集合中

        prop.load(fr);



        prop.setProperty("wangwu", "16");

        FileWriter fw = new FileWriter(file);

        prop.store(fw, "");



        prop.list(System.out);

        fr.close();

    }



    /**

     * 模拟load方法

     * 

     * @throws IOException

     */

    public static void myLoad() throws IOException {

        Properties prop = new Properties();



        BufferedReader bufr = new BufferedReader(new FileReader("info.txt"));



        String line = null;

        while ((line = bufr.readLine()) != null) {

            if (line.startsWith("#"))

                continue;

            String[] arr = line.split("=");

            // System.out.println(arr[0] + "::" + arr[1]);

            prop.setProperty(arr[0], arr[1]);

        }

        prop.list(System.out);

        bufr.close();

    }



    public static void propertiesDemo_4() throws IOException {

        Properties prop = new Properties();



        // 集合中的数据来自于一个文件

        // 注意:必须要保证该文件中的数据时键值对

        // 需要使用到读取流。

        FileInputStream fis = new FileInputStream("info.txt");



        // 使用load方法

        prop.load(fis);

        prop.list(System.out);



    }



    /**

     * 将字符串键值持久化存储到文件中

     * 

     * @throws IOException

     */

    public static void propertiesDemo_3() throws IOException {

        // 创建一个Properties集合

        Properties prop = new Properties();



        // 存储元素

        prop.setProperty("zhangsan", "30");

        prop.setProperty("lisi", "31");

        prop.setProperty("wangwu", "36");

        prop.setProperty("zhaoliu", "20");



        // 将这些集合中的字符串键值信息持久化存储到文件中

        // 需要关联输出流

        FileOutputStream fos = new FileOutputStream("info.txt");



        // 将集合中数据存储到文件中,使用store方法

        prop.store(fos, "info");

    }



    /**

     * 演示Properties集合与流对象相结合的功能

     */

    public static void propertiesDemo_2() {

        // 创建一个Properties集合

        Properties prop = new Properties();



        // 存储元素

        prop.setProperty("zhangsan", "30");

        prop.setProperty("lisi", "31");

        prop.setProperty("wangwu", "36");

        prop.setProperty("zhaoliu", "20");



        prop.list(System.out);// 将键和值打印到控制台



        // prop = System.getProperties();//获取系统信息

        // System.out.println(prop);

    }



    /*

     * Properties集合的存和取

     */

    public static void propertiesDemo() {

        // 创建一个Properties集合

        Properties prop = new Properties();



        // 存储元素

        prop.setProperty("zhangsan", "30");

        prop.setProperty("lisi", "31");

        prop.setProperty("wangwu", "36");

        prop.setProperty("zhaoliu", "20");



        // 修改元素

        prop.setProperty("wangwu", "26");



        // 取出所有元素

        Set<String> names = prop.stringPropertyNames();

        for (String name : names) {

            String value = prop.getProperty(name);

            System.out.println(name + ":" + value);

        }

    }



}


Properties集合应用示例:

package cn.itcase.io.p2.properties;



import java.io.File;

import java.io.FileInputStream;

import java.io.FileOutputStream;

import java.io.IOException;

import java.util.Properties;



/*

 * 定义功能:获取一个应用程序运行的次数,如果超过5次,

 * 给出使用次数已到请注册的提示,并不再运行程序

 * 

 * 思路:

 * 1.需要计数器

 * 每次程序启动计数器需要计数一次,并且是在原有的次数上进行计数;

 * 2.计数器就是一个变量

 * 程序启动时,进行计数,计数器必须存在于内存中并进行运算;

 * 程序结束时,计数器会消失。那么再次启动该程序,计数器就重新被初始化。

 * 需要多次启动同一个应用程序,使用的是同一个计数器。

 * 这就需要计数器的生命周期编程,从内存存储到硬盘文件中。

 * 3.如何使用计数器?

 * 首先,程序启动时,应先读取这个用于记录计数器信息的配置文件,

 * 获取上一次计数次数,并进行试用次数的判断。

 * 其次,对该次数进行自增,并将自增后的次数重新存储到配置文件中。

 * 4.文件中信息的存储和体现

 * 使用键值对。

 * 可以使用有映射关系的map类集合,所以map+io=Properties

 */



public class PropertiesTest {



    /**

     * @param args

     * @throws IOException

     */

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



        getAppCount();

    }



    public static void getAppCount() throws IOException {

        // 将所需的配置文件封装成File对象

        File confile = new File("count.properties");



        if (!confile.exists()) {

            confile.createNewFile();

        }

        FileInputStream fis = new FileInputStream(confile);



        Properties prop = new Properties();

        prop.load(fis);



        // 从集合中通过键获取次数

        String value = prop.getProperty("time");



        // 定义计数器,记录获取到的次数

        int count = 0;

        if (value != null) {

            count = Integer.parseInt(value);

            if (count >= 5) {

                // System.out.println("使用次数已到,请注册!");

                // return;

                throw new RuntimeException("使用次数已到,请注册!");

            }

        }

        count++;



        // 将改变后的次数重新存储到集合中

        prop.setProperty("time", count + "");



        FileOutputStream fos = new FileOutputStream(confile);

        prop.store(fos, "");



        fos.close();

        fis.close();



    }

}



文件清单列表

package cn.itcase.io.p3.test;



import java.io.BufferedWriter;

import java.io.File;

import java.io.FileWriter;

import java.io.FilenameFilter;

import java.io.IOException;

import java.util.ArrayList;

import java.util.List;



/*

 * 获取指定目录下,指定扩展名的文件(包含子目录中的)

 * 这些文件的绝对路径写入到一个文本文件中

 * 

 * 简单说,就是一个指定扩展名的文件列表

 * 

 * 思路:

 * 1.必须继承深度遍历;

 * 2.要在遍历的过程中进行过滤,将符合条件的内容都存储到容器中;

 * 3.对容器中的内容进行遍历,并将内容写入到文件中。

 */

public class Test {



    /**

     * @param args

     */

    public static void main(String[] args) {



        //创建File对象

        File dir=new File("e:\\PalInn");

        

        //实现过滤器

        FilenameFilter filter=new FilenameFilter(){



            @Override

            public boolean accept(File dir, String name) {

                return name.endsWith(".exe");

            }

            

        };

        

        //创建暂存文件列表的list

        List<File> list=new ArrayList<File>();

        

        //遍历文件

        getFiles (dir,filter,list);

        

        //创建要存储信息的目标文件

        File destFile=new File(dir,"exelist.txt");

        

        //将list中存储的信息写入到目标文件中

        write2File(list, destFile);

    }



    /**

     * 对指定目录中的内容进行深度遍历,并按照指定过滤器,进行过滤

     * 

     * @param dir 要遍历的目录

     * @param filter 过滤器

     * @param list 暂存信息的容器

     */

    public static void getFiles(File dir, FilenameFilter filter, List<File> list) {

        File[] files = dir.listFiles();



        for (File file : files) {

            if (file.isDirectory()) {

                // 递归

                getFiles(file, filter, list);

            } else {

                // 对遍历到的文件进行过滤,将符合条件的file对象存储到list集合中

                if (filter.accept(file, file.getName())) {

                    list.add(file);

                }

            }

        }

    }



    public static void write2File(List<File> list, File destFile) {



        BufferedWriter bufw = null;



        try {

            bufw = new BufferedWriter(new FileWriter(destFile));

            for(File file:list){

                bufw.write(file.getAbsolutePath());

                bufw.newLine();

                bufw.flush();

            }

        } catch (IOException e) {

            throw new RuntimeException("写入失败!");

        } finally {

            if (bufw != null)

                try {

                    bufw.close();

                } catch (IOException e) {

                    throw new RuntimeException("关闭失败!");

                }

        }

    }



}


打印流-PrintStream
public class PrintStream extends FilterOutputStream implementsAppendable, CloseablePrintStream
为其他输出流添加了功能,使它们能够方便地打印各种数据值表示形式。
PrintStream 打印的所有字符都使用平台的默认字符编码转换为字节。

package cn.itcase.io.p4.print.demo;



import java.io.IOException;

import java.io.PrintStream;



public class PrintDemo {



    /**

     * @param args

     * @throws 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(97);//a-97,二进制为0110-0001

        out.write(610);// b-98,只写最低8位,610二进制为10 0110-0010



        // out.print(97);//97,保持表示形式。将97先变成字节串保持原样,再打印到目的地



        out.close();



    }



}




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

package cn.itcase.io.p4.print.demo;



import java.io.BufferedReader;

import java.io.FileWriter;

import java.io.IOException;

import java.io.InputStreamReader;

import java.io.PrintWriter;



public class PrintWriterDemo {



    /**

     * @param args

     * @throws IOException

     */

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

        /*

         * PrintWrite 字符打印流

         * 构造函数参数:

         * 1.字符串路径;

         * 2.File对象;

         * 3.字节输出流;

         * 4.字符输出流。

         */

        BufferedReader bufr = new BufferedReader(new InputStreamReader(

                System.in));

        // PrintWriter out = new PrintWriter(System.out, true);// true,自动刷新

        PrintWriter out = new PrintWriter(new FileWriter("out.txt"), true);// true,自动刷新



        String line = null;

        while ((line = bufr.readLine()) != null) {

            if ("over".equals(line))

                break;

            out.println(line.toUpperCase());

            // out.flush();

        }

        out.close();

        bufr.close();

    }



}


序列流-SequenceInputStream
可以对多个流进行合并。(只负责源)
public class SequenceInputStream extends InputStreamSequenceInputStream
表示其他输入流的逻辑串联。它从输入流的有序集合开始,并从第一个输入流开始读取,直到到达文件末尾,接着从第二个输入流读取,依次类推,直到到达包含的最后一个输入流的文件末尾为止。

枚举和迭代:

package cn.itcase.io.p4.sequence.demo;



import java.io.FileInputStream;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.SequenceInputStream;

import java.util.ArrayList;

import java.util.Collections;

import java.util.Enumeration;

import java.util.Iterator;



public class SequenceInputStreamDemo {



    /**

     * @param args

     * @throws IOException

     */

    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"));

        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("4.txt");



        byte[] buf = new byte[1024];



        int len = 0;

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

            fos.write(buf, 0, len);

        }

        fos.close();

        sis.close();

    }



}


文件切割示例:

package cn.itcast.io.p1.splitefile;



import java.io.File;

import java.io.FileInputStream;

import java.io.FileOutputStream;

import java.io.IOException;

import java.util.Properties;



/**

 * 文件切割器

 * @author chenchong

 *

 */



public class SplitFileDemo {



    private static final int SIZE = 1024 * 1024;



    /**

     * @param args

     * @throws IOException

     */

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



        File file = new File("c:\\0.bmp");



        splitFile(file);

    }



    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;



        /*

         * 切割文件时,必须记录被切割文件的名称,以及切割出来的碎片文件的个数,以方便与合并。

         * 这个信息为了进行简单的描述,使用键值对的方式,用到了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");

        fis.close();

    }



}




文件合并示例:

package cn.itcast.io.p1.splitefile;



import java.io.File;

import java.io.FileInputStream;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.SequenceInputStream;

import java.util.ArrayList;

import java.util.Collections;

import java.util.Enumeration;

import java.util.Properties;



/**

 * 文件合并器

 * @author chenchong

 *

 */

public class MergeFile {



    /**

     * @param args

     * @throws IOException

     */

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



        File dir = new File("c:\\partfiles");

        mergeFile(dir);

    }



    public static void mergeFile(File dir) throws IOException {



        /*

         * 获取指定目录下的配置文件对象

         */

        File[] files = dir.listFiles(new SuffixFilter(".properties"));



        if (files.length != 1)// 没有properties,则抛出异常

            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();

    }

}


过滤器:

package cn.itcast.io.p1.splitefile;



import java.io.File;

import java.io.FilenameFilter;



/**

 * 过滤器

 * @author chenchong

 *

 */

public class SuffixFilter implements FilenameFilter {



    private String suffix;

    public SuffixFilter(String suffix) {

        super();

        this.suffix = suffix;

    }

    @Override

    public boolean accept(File dir, String name) {

        return name.endsWith(suffix);

    }



}



操作对象
ObjectInputStream、ObjectOutputStream。
被操作的对象需要实现Serializable(标记接口)。

public interface Serializable
类通过实现 java.io.Serializable 接口以启用其序列化功能。未实现此接口的类将无法使其任何状态序列化或反序列化。可序列化类的所有子类型本身都是可序列化的。序列化接口没有方法或字段,仅用于标识可序列化的语义。

public final void writeObject(Object obj) throws IOException
将指定的对象写入 ObjectOutputStream。对象的类、类的签名,以及类及其所有超类型的非瞬态和非静态字段的值都将被写入

package cn.itcast.io.p1.objectstream;



import java.io.FileInputStream;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.ObjectInputStream;

import java.io.ObjectOutputStream;



import cn.itcast.io.p2.bean.Person;



public class objectStreamDemo {



    /**

     * @param args

     * @throws IOException

     * @throws ClassNotFoundException

     */

    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 {



        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(

                "obj.object"));



        // 对象的序列化。被序列化的对象必须实现Serializalbe接口

        oos.writeObject(new Person("小强", 30));



        oos.close();

    }



}

 

package cn.itcast.io.p2.bean;



import java.io.Serializable;



/*

 * Serializable用于给被序列化的类加入序列号

 * 用于判断类和对象是否是同一版本

 */

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



    /**

     * transient,非静态数据,又不想被序列化,可以使用该关键字修饰。

     */

    private static final long serialVersionUID = 9527L;

    private transient String name;// transient修饰的成员,不写入硬盘

    private int age;



    public Person(String name, int age) {

        super();

        this.age = age;

        this.name = name;

    }



    public Person() {

        super();

    }



    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;

    }



}



RandomAccessFile
随机访问文件,自身具备读写的方
通过skipBytes(int x),seek(int x),来达到随机访问的目的。

public class RandomAccessFile extends Objectimplements DataOutput, DataInput, Closeable
此类的实例支持对随机访问文件的读取和写入。

package cn.itcast.io.p3.randomfiles;



import java.io.IOException;

import java.io.RandomAccessFile;



public class RandomAccessFileDemo {



    /**

     * @param args

     * @throws IOException

     */

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



        /*

         * RandomAccessFile

         * 不是IO体系中的子类;

         * 特点:

         * 1.该对象既能读,又能写;

         * 2.该对象内部维护了一个byte数组,并通过指针可以操作数组中的元素;

         * 3.可以通过getFilePointer获取指针的位置,通过seek方法设置指针的位置;

         * 4.其实,该对象就是将字节输入流和输出流进行了封装;

         * 5.该对象的源或者目的只能是文件,通过构造函数就可以看出;

         */



        // writeFile();

        // readFile();

        randomWrite();



    }



    public static void randomWrite() throws IOException {

        RandomAccessFile raf = new RandomAccessFile("ranacc.txt", "rw");



        // 往指定位置写入数据

        raf.seek(3 * 8);



        raf.write("赵六".getBytes());

        raf.writeInt(102);



        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();

    }



    // 使用RandomAccessFile对象写入一些人员信息

    public static void writeFile() throws IOException {

        /*

         * 如果文件不存在,则创建;如果文件存在,则不创建。

         */

        RandomAccessFile raf = new RandomAccessFile("ranacc.txt", "rw");



        raf.write("张三".getBytes());

        // raf.write(609);//只保留低8位

        // raf.writeInt(609);//先写高位

        raf.writeInt(97);

        // raf.write("小强".getBytes());

        // raf.writeInt(98);



        raf.close();

    }



}


管道流

PipedInputStream、PipedOutputStream

输入输出可以直接进行连接,通过结合线程使用

package cn.itcast.io.p4.piped;



import java.io.IOException;

import java.io.PipedInputStream;

import java.io.PipedOutputStream;



public class PipedStream {



    /**

     * @param args

     * @throws IOException 

     */

    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 {

            Thread.sleep(5000);

            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 {

            out.write("Hey,管道来了!".getBytes());

        } catch (Exception e) {

        }

    }

}



操作基本数据类型
DataInputStream、DataOutputStream

package cn.itcast.io.p5.datastream;



import java.io.DataInputStream;

import java.io.DataOutputStream;

import java.io.FileInputStream;

import java.io.FileOutputStream;

import java.io.IOException;



public class DataStreamDemo {



    /**

     * @param args

     * @throws IOException

     */

    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);

        dis.close();

    }



    public static void writeData() throws IOException {



        DataOutputStream dos = new DataOutputStream(new FileOutputStream(

                "data.txt"));



        dos.writeUTF("你好");



        dos.close();

    }



}


操作字节数组
ByteArrayInputStream、ByteArrayOutputStream
public class ByteArrayOutputStream extends OutputStream
此类实现了一个输出流,其中的数据被写入一个 byte 数组。缓冲区会随着数据的不断写入而自动增长。可使用 toByteArray() 和 toString() 获取数据。

public class ByteArrayInputStream extends InputStreamByteArrayInputStream
包含一个内部缓冲区,该缓冲区包含从流中读取的字节。内部计数器跟踪 read 方法要提供的下一个字节。
关闭 ByteArrayOutputStream、ByteArrayInputStream 无效。此类中的方法在关闭此流后仍可被调用,而不会产生任何 IOException。 (没有调用底层资源)

package cn.itcast.io.p6.bytestream;



import java.io.ByteArrayInputStream;

import java.io.ByteArrayOutputStream;



public class ByteArrayStreamDemo {



    /**

     * @param args

     */

    public static void main(String[] args) {



        ByteArrayInputStream bis = new ByteArrayInputStream(

                "abcdefg".getBytes());



        ByteArrayOutputStream bos = new ByteArrayOutputStream();



        int ch = 0;

        while ((ch = bis.read()) != -1) {

            bos.write(ch);

        }



        System.out.println(bos.toString());

        // bos.close();//无效,不需要关闭

    }



}



简单的编码解码

package cn.itcast.io.p7.encode;



import java.io.UnsupportedEncodingException;



public class EncodeDemo {



    /**

     * @param args

     * @throws UnsupportedEncodingException

     */

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



        /*

         * 字符串——>字节数组,编码

         * 字节数组——>字符串,解码

         * 你好(GBK):-60 -29 -70 -61

         * 你好(UTF-8):-28 -67 -96 -27 -91 -67

         * 

         * 如果编码错误,解码不出来

         * 如果编码正确,解码有可能解出

         */



        String str = "你好";// -60 -29 -70 -61



        byte[] buf = str.getBytes("gbk");



        String s1 = new String(buf, "iso8859-1");//查表错误

        System.out.println("s1=" + s1);//解码错误

        

        byte[] buf2 = s1.getBytes("iso8859-1");//获取源字节

        String s2=new String(buf2,"gbk");//重新解码

        System.out.println("s2="+s2);



        // encodeDemo(str);



    }



    /**

     * @param str

     * @throws UnsupportedEncodingException

     */

    public static void encodeDemo(String str)

            throws UnsupportedEncodingException {

        // 编码

        byte[] buf = str.getBytes("utf-8");

        // printBytes(buf);



        // 解码

        String s1 = new String(buf);

        System.out.println("s1=" + s1);

    }



    public static void printBytes(byte[] buf) {

        for (byte b : buf) {

            System.out.print(b);

        }

    }



}


练习-按字节截取字符串

package cn.itcast.io.p7.encode;



import java.io.IOException;



/*

 * 在java中,字符串"abcd",与字符串"ab你好"的长度是一样的,都是四个字符。

 * 但相应的字节数不同,一个汉字占两个字节。

 * 定义一个方法,按照最大的字节数来取子串。

 * 如:对于"ab你好",如果去三个字节,那么子串就是ab与“你”字的半个,

 * 那么半个就要舍弃。如果取四个字节就是"ab你",去五个字节还是"ab你"

 */

public class Test {



    /**

     * @param args

     * @throws IOException

     */

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



        String str = "ab你好cd谢谢";

        // String str = "ab琲琲cd琲琲";// 琲,-84 105



        // int len = str.getBytes("gbk").length;

        // for (int x = 0; x < len; x++) {

        // System.out.println("截取" + (x + 1) + "个字节结果是:"

        // + cutStringByBytes(str, x + 1));

        // }



        int len = str.getBytes("utf-8").length;

        for (int x = 0; x < len; x++) {

            System.out.println("截取" + (x + 1) + "个字节结果是:"

                    + cutStringByU8Bytes(str, x + 1));

        }

    }



    public static String cutStringByU8Bytes(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)// utf-8码,三个字节组成

            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 cutStringByBytes(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");

    }

}

你可能感兴趣的:(java语言)