第八章 IO(输入输出)


2.引子 

马克-to-win:(视频下载) (全部书籍)对我们编程人员来说,经常需要和IO(输入/输出)系统打交道。包括文件、控制 台、网络连接。神奇的是:java的IO包里的各种各样的类竟然把上面的所有IO情况(文件、控制台、网络连接)都能一把抓轻松搞定。这章我们学文件,控 制台, 下章我们学网络连接。

马克-to-win:(视频下载) (全部书籍)很多老司机还搞不清什么是I什么是O。很简单,我有个土办法。以内存为单位,数据进内存叫In,出内存叫Out。读文件,是数据从硬盘进到内存,所以用in类型流来处理。

马 克-to-win:(视频下载) (全部书籍)当时Sun为什么起名叫流?很多初学的同学有这个疑问,这一流就把他流晕了, 我小学数学老师让我们算张三走路的速度,谁追谁,他一动,像个流一样, 我就晕了。现在我跟大家说,举个例子,这里比如有个文件,java的处理方法是:把硬盘上的文件和内存中我们的一个流绑在一起,当你一个一个的顺序的读流 中的每个字节一遍后,你发现你无形中读了硬盘上的文件一遍。通过这样的方法,你不就能操作硬盘上的文件了吗?当你一个一个的顺序的读流中的每个字节时,像 不像你人不动,站在那里,瞪着眼睛,看着一个小孔,而有一串字节像流水一样,经过小孔。知道Sun为什么当时起名叫“流”了吧!

java当中有两种流,一种是字节流(byte stream): (视频下载) (全部书籍)以1字节(8-bit)为单位进行读/写,一次处理一个字节。另一种是字符流(character stream):,以字符为单位,一次处理一个字符。

马克-to-win:(视频下载) (全部书籍)注意如果当遇到英文时,字符流足够聪明,一次就读一个字节,如遇到中文,一次读两个字节。比如a就占一个字节,即97.见下面的例子。我们摘录一段java官方文档:Each invocation of one of an InputStreamReader's read() methods may cause one or more bytes to be read from the underlying byte input stream.



第一节 字节流


本节我们只讲字节流,字符流将来再讲。马克to-win:Sun设计者决定字节流中与输出有关的所有类都从OutputStream继承,而与输入有关的所有类都从InputStream继承。

1.输出流

既 然输出字节流中所有类都从 OutputStream继承,每个类都有自己专门的功能。(否则继承出来有什么用呢?)我们常用的输出字节流都有PrintStream, FileOutputStream,BufferedOutputStream,DataOutputStream, ObjectOutputStream 。。。下面我们一一给予介绍,更多未提到的可去文档中查阅,大同小异。



1.1 FileOutputStream的用法  (视频下载) (全部书籍)

FileOutputStream是OutputStream的继承类,从字面上就可看出,它的主要功能就是能向磁盘上写文件。write方法会把字节一个一个的写入磁盘中。



例:1.1.1

import java.io.*;
public class TestMark_to_win {
    public static void main(String args[]) throws Exception {
        FileOutputStream f = new FileOutputStream("c:/4.txt");
        /*后面的write方法里面调用了c语言里面open方法。里面有native void open(String name)
         */
        byte aa = 97;
        f.write(aa);
        char bb = 'b';
/*没有write(char),只能机器自动转从char到int*/        
        f.write(bb);

        int cc = 99;
        f.write(cc);
        // String kk1="97";
        // f.write(kk1);//error, because FileOutputStream does not have
        // write(String) method.must use PrintStream.
    }
}


输出的结果是:
在4.txt文件中我们写入了:
abc


1.2 PrintStream的用法  (视频下载) (全部书籍)

马 克-to-win:从学java第一天,我们就经常用到System.out.println(),实际上查阅文档可知,System.out就是Sun 编的一个PrintStream的实例对象。PrintStream顾名思义,Sun编它,就是用来打印的,以各种各样的格式,打印各种各样的数据, (boolean,char,double,float)。下面的例子就介绍了println(int x),print(String)和print(char c)的用法。




例:1.2.1

import java.io.*;
public class TestMark_to_win {
    public static void main(String args[]) throws Exception {
        byte inp[] = new byte[3];
        inp[0] = 97;inp[1] = 98;inp[2] = 99;
        for (int i = 0; i < 3; i++) {
            /*there is no such method as println(Byte x), only sun. have the
following public void println(int x) if you want to print out
"a", use System.out.println((char)inp[i]);*/
            System.out.println(inp[i]);
        }

        for (int i = 0; i < 3; i++) {
/*public void print(char c)Print a character.*/
            System.out.println((char) inp[i]);
        }
        char c='z';
        System.out.println(c);
        String s="我们是good123";
        System.out.println(s);
        double d=3.14;
        System.out.println(d);
    }
}
       



结果是:
97
98
99
a
b
c
z
我们是good123
3.14



例:1.2.2

import java.io.*;
public class TestMark_to_win {
    public static void main(String args[]) throws Exception {
        String m = "qi hello bye97我们";
        FileOutputStream f2 = new FileOutputStream("i:/4.txt");
        PrintStream ps = new PrintStream(f2);
        /*void println(String x) Print a String and then terminate the line.
*/
        ps.println(m);
        /*Close the stream. This is done by flushing the stream and then
closing the underlying output stream. Close the stream.
the close statement can be commented out, still things can be print to
the file, but for the writer's example---ReaderWriter.java, you must
use close , otherwise nothing can be printed out to the file, because
reader's close is not the same as stream's close.*/
        char c='z';
        ps.println(c);
        byte b=97;
        ps.println(b);
        double d=3.14;
        ps.println(d);
        ps.close();
    }
}
输出的结果是:
在4.txt文件中我们写入了:
qi hello bye97我们
z
97
3.14



1.3 BufferedOutputStream的用法 (视频下载) (全部书籍)
马克-to-win:BufferedOutputStream 顾名思义就是它有一个内部的buffer(缓存),当写数据时,可以批量的写。它的工作原理和BufferedIputStream一样,包括例子,请参考下文的BufferedInputStream。


1.4 DataOutputStream的用法 (视频下载) (全部书籍)
马克-to-win:一定要注意DataOutputStream 与DataInputStream必须配合使用,以便将基本数据类型(int,char,long,String等)写入一个数据流。详细讲解请见下面的DataInputStream部分。


1.5 ObjectOutputStream的用法  (视频下载) (全部书籍)
马 克-to-win:顾名思义,ObjectOutputStream一定是用来往输出流上写用户自定义的对象的。比如数据库中某表的一行数据对应一个对 象,这时可通过这种方法存在硬盘上。一定要注意ObjectOutputStream与ObjectInputStream必须配合使用,且按同样的顺 序。例子参见ObjectInputStream那部分的描述。


2.输入流

既 然输入字节流中所有类都从InputStream继承,每个类都有自己专门的功能(否则继承出来有什么用呢?)我们常用的输入字节流都有 InputStream,FileInputStream,BufferedInputStream,DataInputStream, ObjectInputStream。。。下面我们一一给予介绍,更多未提到的可去文档中查阅,大同小异。


2.1 InputStream的用法 (视频下载) (全部书籍)

InputStream 是个抽象类,有个抽象方法read(),即一次读一个字节。马克-to-win:前面我们经常用到System.out.println(),实际上同样 经常用的System.in就是Sun编的一个InputStream的实例对象。它的read方法就是一次从控制台读入一个字节。下面的实验会证明它无 法直接处理中文, 需要将来用到字符流。


例:2.1.1

import java.io.*;
public class TestMark_to_win {
    public static void main(String args[]) throws Exception {
        byte inp[] = new byte[4];

        for (int i = 0; i < 4; i++) {
/* 这里的read方法,一次读一个字节。Reads the next byte of data from the input stream. The value byte is returned as an int in the range 0 to 255.  so you must cast by yourself. when you run, you type in abcd, This method blocks until input
 data is available,
*/
            inp[i] = (byte) System.in.read();
        }
        for (int i = 0; i < 4; i++) {
            System.out.println(inp[i]);//打出数字
        }

        for (int i = 0; i < 4; i++) {
            System.out.println((char) inp[i]);//打出字符
        }

    }
}
结果:
abcd
97
98
99
100
a
b
c
d

我们再次运行,输入中文,证明InputStream直接无法处理中文。

结果是:
我们
-50
-46
-61
-57
?
?
?
?


2.2 FileInputStream的用法 (视频下载) (全部书籍)

FileInputStream是InputStream的继承类,从字面上就可看出,它的主要功能就是能从磁盘上读入文件。read方法会一个一个字节的从磁盘往回读数据。

例:2.2.1

import java.io.*;
public class TestMark_to_win {
    public static void main(String args[]) throws Exception {
        int size;
        FileInputStream f1 = new FileInputStream("c:/1.txt");
        /*Returns the number of bytes that can be read from this file input
stream without blocking.*/
        size = f1.available();
        for (int i = 0; i < size; i++) {
            /*Reads a byte of data from this input stream. This method blocks
if no input is yet available. Returns: the next byte of data, or
-1 if the end of the file is reached.*/
            System.out.println((char) f1.read());

        }

        int size2;
        FileInputStream f2 = new FileInputStream("c:/1.txt");
        size2 = f2.available();
        for (int i = 0; i < size2; i++) {
            /* you use the next statement, only int value can be printed out. */
            System.out.println(f2.read());

        }

    }
}


我的c盘下的1.txt文本是:

ab我们ab


程序运行结果是:

a
b
?
?
?
?
a
b
97
98
206
210
195
199
97
98


例:2.2.2(下面是一个较笨的拷贝程序,初学者好理解)

import java.io.*;
public class TestMark_to_win {
    public static void main(String[] args) throws IOException {
        File inputFile = new File("i:/1.txt");
        File outputFile = new File("i:/1_c.txt");
        FileInputStream in = new FileInputStream(inputFile);
        FileOutputStream out = new FileOutputStream(outputFile);
        int c;
        while ((c = in.read()) != -1)
            out.write(c);
        in.close();
        out.close();
    }
}



2.3 BufferedInputStream的用法 (视频下载) (全部书籍)
马克-to-win:BufferedInputStream 顾名思义就是它有一个内部的buffer(缓存),它的read方法表面上看,虽然是只读了一个字节,但它是开始时猛然从硬盘读入一大堆字节到自己的缓 存,当你read时,它是从缓存读进一个字节到内存。而前面讲的FileInputStream字节流,read时,都是真正每个字节都从硬盘到内存,是 很慢的。为什么?请研究硬盘的结构!下面的两个例子,一个是FileInputStream的read生读进来的,另一个是BufferedInputStream的只能read,你比较一下读的时间,差距蛮大的!

例:2.3.1

import java.io.*;
public class TestMark_to_win {
    public static void main(String args[]) throws FileNotFoundException,
            IOException {
        FileInputStream fis = new FileInputStream("c:/2.txt");
        long t = System.currentTimeMillis();
        int c;
        while ((c = fis.read()) != -1) {}
        fis.close();
        t = System.currentTimeMillis() - t;
        System.out.println("遍历文件用了如下时间:" + t);
    }
}

结果是:

遍历文件用了如下时间:453




例:2.3.2

import java.io.*;
public class TestMark_to_win {
    public static void main(String args[]) throws FileNotFoundException,
            IOException {
        FileInputStream fis = new FileInputStream("i:\\2.txt");
        BufferedInputStream bis = new BufferedInputStream(fis);
        long t = System.currentTimeMillis();
        int c;
        /*even though the next read() also read one byte, but because
BufferedInputStream has an internal buffer,when first time to read,
it will read in a whole buffer of byte from hard disk, then digest
these bytes one by one in memory */
        while ((c = bis.read()) != -1) {}
        fis.close();
        t = System.currentTimeMillis() - t;
        System.out.println("遍历文件用了如下时间:" + t);
    }
}

结果是:
遍历文件用了如下时间:16


下面的例子讲述BufferedInputStream的read(byte b[], int off, int len)的用法。即真正的批量读入。正好前面讲到BufferedOutputStream时,还欠大家一个例子。

例:2.3.3  

import java.io.*;
public class TestMark_to_win {
    public static void main(String[] args) {
        String source = "c:\\2.txt";
        String dest = "c:\\2_copy.txt";
        try {
            FileInputStream fis = new FileInputStream(source);
            BufferedInputStream bis = new BufferedInputStream(fis);
            FileOutputStream fos = new FileOutputStream(dest);
            BufferedOutputStream bos = new BufferedOutputStream(fos);
            int readcount;
            byte[] readbyte = new byte[256];
            /* public synchronized int read(byte b[], int off, int len) Reads
bytes from this byte-input stream into the specified byte array,
starting at the given offset.
@param b destination buffer.
@param off offset at which to start storing bytes.
@param len maximum number of bytes to read.
@return the number of bytes read, or <code>-1</code> if the end
of the stream has been reached.
@exception IOException if an I/O error occurs.*/
            while ((readcount = bis.read(readbyte, 0, readbyte.length)) != -1) {
                bos.write(readbyte, 0, readcount);
            }
            bis.close();
            bos.close();
            System.out.println("复制完毕!");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

结果是:

复制完毕!



2.4 DataInputStream的用法 (视频下载) (全部书籍)
马 克-to-win:DataInputStream顾名思义:就是专门用来读各种各样的数据的,比如(int,char,long等),一定要注意 DataOutputStream 与DataInputStream配合使用,而且二者读写的顺序要一样,可以参照下面的例子。

例:2.4.1

import java.io.*;
public class TestMark_to_win {
    /* when run this program, no need any data.dat file, because it can generate
the file.anyway,this file can not be recognized by humanbeing
*/
    public static void main(String[] args) throws IOException {
        FileOutputStream fos = new FileOutputStream("c:/data.txt");

        DataOutputStream dos = new DataOutputStream(fos);

        dos.writeInt(345);

        dos.writeDouble(4.54);

        dos.writeUTF("我们");
        dos.close();

        FileInputStream fis = new FileInputStream("c:/data.txt");
        DataInputStream dis = new DataInputStream(fis);
        /*1) a data output stream to write data that can later
be read by a data input stream. 2)note the sequence.first write what,
then read what. if you comment out the following statment,the result
is not correct, because the sequence is chaotic.I tried. 3) readInt()
Returns: the next four bytes of this input stream, interpreted as an
int. */
        System.out.println(dis.readInt());
        System.out.println(dis.readDouble());
        System.out.println(dis.readUTF());
        dis.close();

    }
}
结果是:
345
4.54
我们

当我们用记事本观察所写的文件时:data.txt里面的内容是:  Y@(趼廫) 鎴戜滑  我们并看不懂内容。


2.5 ObjectInputStream的用法 (视频下载) (全部书籍)
马克-to-win:ObjectInputStream顾名思义就是可以从流中读入一个用户自定义的对象。一定要注意ObjectOutputStream与ObjectInputStream必须配合使用,且按同样的顺序。

例:2.5.1

import java.io.Serializable;
//类必须实现Serializable接口才可以被序列化, otherwise report error of java.io.NotSerializableException: J10.Employee
public class Employee implements Serializable {
    private String name;
    private int id;

    public Employee(String name,int id){
        this.name = name;
        this.id = id;
    }

    public void showInfo(){
        System.out.println("name:" + name + "\tid:" + id );
    }
}


例:2.5.2

import java.io.*;
public class TestMark_to_win {
    public static void main(String[] args) throws IOException{
            FileOutputStream fos = new FileOutputStream("c://data.txt");
            ObjectOutputStream oos = new ObjectOutputStream(fos);
            oos.writeObject(new Employee("张三",1));
            oos.writeObject(new Employee("李四",2));
            oos.close();
    }
}


例:2.5.3

import java.io.*;
public class TestMark_to_win {
    public static void main(String[] args) throws IOException, ClassNotFoundException{
            FileInputStream fis = new FileInputStream("c://data.txt");
            ObjectInputStream ois = new ObjectInputStream(fis);
            Employee e1 = (Employee)ois.readObject();
            Employee e2 = (Employee)ois.readObject();
               
            e1.showInfo();
            e2.showInfo();
            ois.close();
    }
}


输出结果是:

name:张三    id:1
name:李四    id:2




第二节 File类

2.1 File的用法 (视频下载) (全部书籍)

马 克-to-win:sun公司设计File类,本身不能用来读数据或写数据。(要想读写数据,必须和其它io流的类配合使用,比如 FileInputStream等)File类的功能就是对磁盘上的文件或目录做一些非读写方面的工作,比如看看文件在哪个目录,哪天创建的,创建个新空 文件等。

例:2.1.1


import java.io.*;
public class TestMark_to_win {

    public static void main(String args[]) throws Exception {
/*File(String parent, String child) Creates a new File instance from a
parent pathname string and a child pathname string.the parent  pathname is taken to denote a directory, and the child pathname string is taken to denote either a directory or a file.  */
        File f1 = new File("c:\\tmp", "tmp\\1.txt");
 //File f1=new File("1.txt");
/*getName就是lastname*/
        System.out.println("getName is " + f1.getName());
/* getPath Returns: The string form of this abstract pathname。即原样返回。 */
        System.out.println("getPath is" + f1.getPath());
/* getAbsolutePath: Returns the absolute pathname string of this
abstract pathname. If this abstract pathname is already absolute,
then the pathname string is simply returned as if by the getPath()
method.if you use File f1=new File("1.txt"); you can see the
difference.结果会变成
getName is 1.txt
getPath is1.txt
Absolute Path is D:\eclipseJee\t1\1.txt
not */
        System.out.println("Absolute Path is " + f1.getAbsolutePath());
        System.out.println(f1.exists() ? "exist" : "not");
    }
}
结果是:
getName is 1.txt
getPath isc:\tmp\tmp\1.txt
Absolute Path is c:\tmp\tmp\1.txt
not


例:2.1.2

import java.io.*;
public class TestMark_to_win {
    public static void main(String[] args) {
        File path = new File("c:/");
        /*Returns an array of strings naming the files and directories .*/
        String[] list = path.list();
        for (int i = 0; i < list.length; i++)
            System.out.println(list[i]);
    }
}
结果是:

$360Section
1.txt
2.txt
2_copy.txt
3.txt
360Rec
360SANDBOX
360安全浏览器下载
4.txt
91UserData
Adobe
AUTOEXEC.BAT
AVScanner.ini
BlueStacks_Green
boot.ini
bootfont.bin
Config.Msi
CONFIG.SYS
data.txt
dell
desktop.ini
Documents and Settings
Drivers
EasyGameUserData
FFOutput
InstallConfig.ini
IO.SYS
KPCMS
KwDownload
MSDOS.SYS
MSOCache
my_vod_caching
NTDETECT.COM
ntldr
out.txt
pagefile.sys
ppsfile
Program Files
QMBackup
QMDownload
RECYCLER
screenshot.png
SecurityScanner.dll
SogouPY
StormMedia
System Volume Information
temp
uacdump
vcredist_x86.log
WINDOWS


例:2.1.3(初学者可略过)

import java.io.*;
class MyFilenameFilter implements FilenameFilter {
    /*public boolean accept(File dir,String name) Tests if a specified file
should be included in a file list.\u00A0
Parameters: dir - the directory in which the file was found. qixy: dir is
the caller in the dir.list(myFilenameFilter) name - the name of the
file.\u00A0 Returns: true if and only if the name should be included in
the file list; false otherwise. */
    public boolean accept(File dir1, String name) {
        System.out.println("here" + dir1.getAbsoluteFile());
        System.out.println(name + "hereend");
        boolean flag = (name.indexOf(".txt") != -1);
        return flag;
    }
}

public class TestMark_to_win {
    public static void main(String[] args) throws IOException {
        File dir = new File("c:");
        MyFilenameFilter myFilenameFilter = new MyFilenameFilter();
        /*String[] list (FilenameFilter filter) Returns an array of strings
naming the files and directories in the directory denoted by this
abstract pathname that satisfy the specified filter. 马克-to-win: if dir has
10 files. list method will call accept(File dir, String name1) 10
times, name1 is the\u00A0 name of one of the 10 files which is inside
this directory.\u00A0*/
        String[] names = dir.list(myFilenameFilter);
        for (int i = 0; i < names.length; i++) {
            System.out.println(names[i]);
        }
    }

}

 

result is:

herec:\
$360Sectionhereend
herec:\
1.txthereend
herec:\
InstallConfig.inihereend
herec:\
my_vod_cachinghereend
herec:\
StormMediahereend
herec:\
System Volume Informationhereend
herec:\
temphereend
herec:\
test.txthereend
herec:\
uacdumphereend
herec:\
vcredist_x86.loghereend
herec:\
WINDOWShereend
1.txt
1_c.txt
2.txt
2_copy.txt
3.txt
4.txt
data.txt
out.txt
test.txt



第三节 字符流


本节我们只讲字符流。马克to-win:Sun设计者决定字符流中与输出有关的所有类都从Writer继承,而与输入有关的所有类都从Reader继承。

1.输出流

既 然输出字符流中所有类都从 Writer继承,每个类都有自己专门的功能。(否则继承出来有什么用呢?)我们常用的输出字符流都有FileWriter,PrintWriter 。。。下面我们一一给予介绍,更多未提到的可去文档中查阅,大同小异。



1.1 FileWriter的用法 (视频下载) (全部书籍)

FileWriter是Writer的继承类,从字面上就可看出,它的主要功能就是能向磁盘上写文件。write方法会把字符一个一个的写入磁盘中。

例:1.1.1

import java.io.*;
public class TestMark_to_win {
    public static void main(String[] args) throws IOException {
        File file = new File("c:\\test.txt");
        FileWriter fw = new FileWriter(file);

/*void java.io.OutputStreamWriter.write(int c) throws IOException
Writes a single character.
Parameters:
c int specifying a character to be written*/

        fw.write(97);

/*void java.io.Writer.write(String str) throws IOException
Writes a string.
Parameters:
str String to be written
*/

        fw.write("this is 我们");
        fw.close();
    }
}


输出的结果是:
athis is 我们


1.2 PrintWriter的用法 (视频下载) (全部书籍)

马 克-to-win:PrintWriter和PrintStream类似,只不过PrintStream是针对字节流的,而PrintWriter是针对字符流的。


例:1.2.1

import java.io.*;
public class TestMark_to_win {
    public static void main(String args[]) throws Exception {
        String s1 = "我们" + "\n";
        String s2 = "你们" + "\n";
        PrintWriter p = new PrintWriter("c:/out.txt");
        p.println("output" + s1);
        p.println("output" + s2);
        /*without using the following statement, the file name can be write out, but the content of the file is empty. */
        p.close();
    }
}


结果是:

output我们

output你们



2.输入流

既 然输入字符流中所有类都从Reader继承,每个类都有自己专门的功能。(否则继承出来有什么用呢?)我们常用的输入字符流都有StringReader,FileReader,BufferedReader,InputStreamReader 。。。下面我们一一给予介绍,更多未提到的可去文档中查阅,大同小异。


2.1 StringReader的用法 (视频下载) (全部书籍)

StringReader是Reader的继承类,从字面上就可看出,它是专门处理字符串的。

例:2.1.1

import java.io.*;
public class TestMark_to_win {
    public static void main(String args[]) throws Exception {
        // /////from multiline string to StringReader, then to console
        String s, s1 = new String();
        s = "你们" + "他们a我们" + "\n";
        System.out.println(s);
        /* A character stream whose source is a string. */
        StringReader in2 = new StringReader(s);
        int c;
        /*in2.read() Read a single character,(qixy: two bytes 或1个字节, so can handle chinese). or -1 if the end of the stream has been reached. Returns: The character read */
        while ((c = in2.read()) != -1) {
            System.out.println((char) c);
        }

    }
}



结果:

你们他们a我们





a




2.2 FileReader的用法 (视频下载) (全部书籍)

FileReader是Reader的继承类,从字面上就可看出,它的主要功能就是能从磁盘上读入文件。read方法会一个一个字符的从磁盘往回读数据。

例:2.2.1

import java.io.*;
public class TestMark_to_win {
    public static void main(String args[]) throws Exception {
        /*public int read()
         throws IOException
Reads a single character.
Overrides:
read in class Reader
Returns:
The character read, or -1 if the end of the stream has been reached
Throws:
IOException - If an I/O error occurs */
        int ii;
        FileReader in = new FileReader("c:/1.txt");
        while ((ii = in.read()) != -1) {
            System.out.println(ii);
        }
        in.close();
        FileReader in1 = new FileReader("c:/1.txt");
        while ((ii = in1.read()) != -1) {
            System.out.println((char)ii);
        }
        in1.close();
    }
}

结果:

97
98
25105
20204
97
98
a
b


a
b



例:2.2.2(一个简单的拷贝方法,初学者方便理解)

import java.io.*;
public class TestMark_to_win {
    public static void main(String[] args) throws IOException {
        File inputFile = new File("c:/1.txt");
        File outputFile = new File("c:/1_c.txt");
        FileReader in = new FileReader(inputFile);
        FileWriter out = new FileWriter(outputFile);
        int c;
        while ((c = in.read()) != -1)
            out.write(c);
        in.close();
        out.close();
    }
}



2.3 BufferedReader的用法 (视频下载) (全部书籍)
马克-to-win:BufferedReader和BufferedInputStream差不多,只不过一个处理字符,一个处理字节。buffer(缓存)什么的原理都是一样的。

例:2.3.1


import java.io.*;
public class TestMark_to_win {
    public static void main(String args[]) throws Exception {
        /* from file to string then to "multiline string" then to console. */
        String s2, s3 = new String();
        /*Creates a new FileReader, given the name of the file to read from.BufferedReader(Reader in) Create a buffering character-input stream
that uses a default-sized input buffer.*/
        BufferedReader in = new BufferedReader(new FileReader("c:/4.txt"));
        /*readLine is a method from BufferedReader: Read a line of text.
Returns: A String containing the contents of the line, not including
any line-termination characters, or null if the end of the stream has
been reached */
        while ((s2 = in.readLine()) != null) {
            s3 += s2 + "\n";
        }
        System.out.println(s3);
        in.close();
    }
}

结果:

qi hello bye97我们
z
97
3.14


例:2.3.2

import java.io.*;
public class TestMark_to_win {
    public static void main(String args[]) throws Exception {
        // /////////////////////// from StringReader to file:
        String s = "你们" + "\n" + "他们我们" + "\n";
        String s1 = "";
        StringReader in2 = new StringReader(s);
        in2.reset();
        BufferedReader in4 = new BufferedReader(in2);
        while ((s1 = in4.readLine()) != null) {
            System.out.println("output" + s1);
        }
    }
}


结果:

output你们
output他们我们



2.4 InputStreamReader的用法 (视频下载) (全部书籍)
马 克-to-win:InputStreamReader 从文字上分析:InputStream是字节流的意思,Reader是字符流的意思。InputStreamReader这个类就是用来把字节流转换成字符流的。System.in代表控制台输入。它天生是个字节流。参见我前面写的InputStream小节的例:2.1.1, 我们发现如果向控制台输入中文,控制台是处理不了的,但这时如果我们用InputStreamReader这个工具转换一下,问题就解决了。下一章我们要 讲的网络传输,天生也是以字节形式进行的,所以字节流和字符流之间也必然转换一下。


例:2.4.1

import java.io.*;
public class TestMark_to_win {
    public static void main(String args[]) throws Exception {
        // ////////////////from console to string,\u00A0
        System.out.println("from console to string ");
        /*An InputStreamReader is a bridge from byte streams to character streams: It reads bytes and decodes them into characters using a specified charset. The charset that it uses may be specified by name or may be given explicitly, or the platform's default charset may be accepted. InputStreamReader(InputStream in) Create an
InputStreamReader that uses the default charset.
 */
        BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
        String stdinS;
        stdinS = stdin.readLine();
        System.out.println(stdinS);
    }
}

结果是:

from console to string
我们正在学java
我们正在学java



 

作业:
1) 做一个拷贝程序,它能拷贝gif或exe文件。
2)判断d:\tmp\1.txt这个文件是否为directory,file,可读?可写?(提示:File f1,f1.isDirectory(),f1.isFile(),f1.canRead(),f1.canWrite().
3) 从命令行输入参数判断此文件是否为普通文件,如是打印出来内容。(提示:for(int i=0;i<args.length;i++) {l.add(args[i]);} 先用File, 再用FileReader.
4) 把你在Console 中敲入的几行字符添加到一个文件的最后。(提示:FileWriter(String fileName, boolean append)
敲入“end”,返回,
while(!(temp=br.readLine()).equals("end")){)

课外题:
1)查一个文件中是否有"abc" 这个字符串,(用FileReader或read a line,读到一个String中)
2)把文件1反转后输出到文件2(i按行,ii按字【先按行】),(提示:stack,read,fileReader)
3) a file: zs 1000
           ls 2000
           ww 2500
 you can get a name from console, then you raise 500 salary for the person whose name is just input. then you save the whole data in a new file.(hint: use Hashtable,LinkedHashMap?)
3.5) sort the data from the above file according to name, then output the result,(use treeset and hastable,TreeMap?


项目(创建一门新程序语言"j+"):
(视频下载) (全部书籍)

背景:java语言的并发操作当遇到共享资源时,因为无序竞争,导致效率降低.我们会模仿apache的spark大数据处理引擎的scala语言一样,创建一种类java的语言,名称“j+",它的优势是并发线程操作共享资源靠进入队列而提高性能。它的多线程模型是actor模型.它有内置的数据结构如list,map,queue.自带io,网络和jdbc.结合zookeeper的优点?
第一步规划:能够识别符号+,-,*,%(注意这个是除号,而不是/),;,和一些关键字。比如for,if,(),
实现方法:1)把a%b+c变成 a/b+c ,之后写入一个新的文件就行了。因为我们的语言是转成java语言,所以比较简单。但如果从java语言转成汇编语言,就不那么容易了。a+b/c需要在符号表中先确定加号和除号的优先级才能确定是先要做b除以c,在做加a的运算。
2)动态调用javac:
      Runtime rt = Runtime.getRuntime();
      Process ps = rt.exec("cmd /c javac " + fileName);
      ps.waitFor();
      Process ps1 = rt.exec("cmd /c copy " + className+" bin");
可运行通的程序,在我的机器目录里。

第二步规划:queue,list,set,stack都是内置自带的。io,jdbc,socket,也都是自带的。

第三步规划:并发处理,使用actor模型。对共享数据的访问,例如buyTicket(instance,2),此方法里第一件事是把动作放入队列。queue.add(instance,buyTicket,2);if(engine.noStart()) startEngine();    在startEngine中就是到队列中去,去一条一条执行buyTicket。如果线程中有人要想取消排队,只需令自己实例的absence成员变量为真就好了。而刚才队列在执行 buyTicket时加以判断是否absence既可。

项目二:(视频下载) (全部书籍)
我们来自己从头做一个类似oracle的数据库。但是由于时间的关系,优化的工作先不必考虑。
0)在eclipse控制台,程序一运行首先输出让你输入用户名和密码,你必须输入缺省的用户名和密码。
1)你要有一个元数据文件,比如存放表名(字段名1,字段名2,,,,,),我们暂时考虑所有字段都是字符串或int类型的。
2)当你insert into table1(a,b,c)时,你就会把abc这三个数据写到table1这个文件当中一行,假如数据缺失,就用null或0代替。
3)当你select abc from table2 where
m=n时,你就到table2文件当中,一行一行筛选,选出m等于n那一行。之后吧,abc那一列的数据返回来。
有关事务的问题解决方法。请参考我的并发操作那一章。通过这个项目,你在学我的数据库优化处理方案那门课就会简单得多。