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

posted on 2012-08-14 19:39  foolchen  阅读(442)  评论(0编辑  收藏  举报

导航