技术头条 - 一个快速在微博传播文章的方式     搜索本站
您现在的位置首页 --> Java --> [Java基础教程]第十二章-Java输入输出流

[Java基础教程]第十二章-Java输入输出流

浏览:2249次  出处信息

虽然计算机的历史才六七十年,但是研究机器计算的历史非常久远,历史上很多杰出的数学家使用10进制进行了大量的研究,20世纪人类使用电位表示2进制(0,1),计算机才有了飞速的发展。计算机的存储和网络传输都是2进制,每个位为一个bit,每8bit为一个字节。后来计算机的用途逐渐从纯粹的数学计算扩展到各个方面,为了表示文字使用固定2进制串表示各种字符集,这种方式叫编码。目前存在的编码方式各种各样,其中我们会用到的包括ASCII主要表示英文相关字母和符号,GBK编码双字节表示中文常用字符集,UTF-8使用1-3个字节常用中文字符集。如果不涉及与GBK字符集编码的应用交互,最好使用UTF-8字符集进行开发。

日常开发中经常会有访问文件的场景,Java为这种场景提供了几个工具类。

public static void main(String[] args) throws IOException {
    File fileTest = new File("test.txt");// 这里不是真的创建一个文件
    System.out.println("文件是否存在:" + fileTest.exists());
    if (!fileTest.exists()) {
        fileTest.createNewFile();// 这里才是创建文件
    }
    System.out.println("第二次检查文件是否存在:" + fileTest.exists());
    System.out.println("文件路径:" + fileTest.getAbsolutePath());
}

上面的代码的功能是:获取一个文件句柄,如果文件不存在则创建文件,打印文件的绝对路径。运行上面的代码后刷新一下工程文件,看是否创建一个了个”test.txt”的文件。
File文件类,描述文件(无论是否存在)的信息,exists检查文件是否存在,createNewFile创建文件,getAbsolutePath获取文件绝对路径。有绝对路径就有相对路径,这里的相对路径是指相对于运行时的跟路径,“File fileTest = new File(“test.txt”);”就是使用的相对路径,根据打印的结果我们可以看出来工程运行的根路径为”D:itemslearntest”(不同的机器路径不一样),就是工程的根路径。

根据后缀名(.txt)可以看出,我们创建的是一个文本文件,老规矩向文件中输入“Hello World,你好中国”。

FileOutputStream fos = new FileOutputStream(fileTest);// 文件输出字节流
OutputStreamWriter osw = new OutputStreamWriter(fos);// 字节流向字符流转换 默认为UTF-8编码方式
BufferedWriter bw = new BufferedWriter(osw);// 缓存字符输出流
bw.write("Hello World,你好中国");
bw.flush(); // 刷新缓存,防止未写入文件
bw.close(); // 流关闭
osw.close(); // 流关闭
fos.close(); // 流关闭
System.out.println("写入完毕");

Java的文件访问方式经常被吐槽,使用太复杂,各种流类型不断转换 ,如下图所示:

输入输出流

通常文件(文本文件)的访问需要至少3个流,因为文件的存储和传输都是2进制数字,所以先获取字节流OutputStream/InputStream,然后把字节流使用相应的编码方式转换成字符流Writer/Reader,字符流只能单字符传输效率太低,所以又引入一个缓冲字符流BufferedWriter/BufferedReader,缓冲区满了才做输入或者输出操作。BufferedWriter.write(String)作用是把参数的字符串输入到文件中,如果需要换行字符串中添加”n”就可以。如果入参数据太少可能会导致缓冲区没有写满,如果我们不调用flush,可能数据没有真正的写入文件,所以使用BufferedWriter写入后一定要flush。最后记得关闭流,否则可能导致内存丢失。当我们运行多次后,发现文件中仍然就一句”Hello World,你好中国”,内容覆盖了,所以如果需要在文件尾部添加需要使用BufferedWriter.append(String),并且FileOutputStream初始化时设置是否追加为true。

FileInputStream pis = new FileInputStream(fileTest, true);
InputStreamReader isr = new InputStreamReader(pis);
BufferedReader br = new BufferedReader(isr);
String line = br.readLine();// 先读取一行
while (line != null) { // 如果不为空继续读取直到为Null
    System.out.println(line);
    line = br.readLine();
}
br.close();
isr.close();
pis.close();

读取文件时,因为无法确定文件的有多少数据,所以要循环读取直到没有数据返回。

除了文件中读取数据,通过网络也可以读取或者写入数据,同样是使用输入输出流交互,下面我们做一个简单的服务器和客户端的交互测试。

public static void main(String[] args) throws IOException {
    ServerSocket serverSocket = new ServerSocket(8080);
    System.out.println("监听IP:" + serverSocket.getInetAddress().getLocalHost().getHostAddress() + "; 监听端口:"
                + serverSocket.getLocalPort());
    Socket acceptSocket = serverSocket.accept();
    InputStream inputStream = acceptSocket.getInputStream();
    InputStreamReader isr = new InputStreamReader(inputStream, "utf-8");
    BufferedReader br = new BufferedReader(isr);
    String line = null;
    while ((line = br.readLine()) != null) {
            System.out.println("客户输入:" + line);
    }
    br.close();
    isr.close();
    serverSocket.close();
    System.out.println("输出结束");
}

启动后使用telnet客户端可以连接并交互:
启动链接telnet 192.168.0.6 8080,注意ip和端口换成自己的

telnet连接

交互结果,分别输入了”hello”和”bye”

telnet连接输出结果
下面我们再看一下测试客户端代码:

public static void main(String[] args) throws UnknownHostException,
            IOException {
    Socket socket = new Socket("127.0.0.1", 8080);
    OutputStream outputStream = socket.getOutputStream();
    BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(
                outputStream));
    writer.write("hin");
    writer.flush();
    writer.write("my name is lilein");
    writer.flush();
    writer.write("byen");
    writer.flush();
    writer.close();
    outputStream.close();
    socket.close();
}

通过网络的数据交互使用的也是输入流和输出流,多了ServerSocket,Socket用于描述网络连接。网络就是IP:Port进行连接的。

小练习:
读取练习工程中所有的java文件,并统计字母a-z出现的次数(不区分大小写)。

课程中使用的代码:

package com.sunhaojie.learntest.twelfth;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
/**
 * @ClassName FileTest
 * @Description 文件测试类
 *
 * @author sunhaojie 3113751575@qq.com
 * @date 2016年2月12日 下午9:14:24
 */
public class FileTest {
    /**
     * @Title main
     * @Description 测试File类
     * @param args
     * @return void
     *
     * @author sunhaojie 3113751575@qq.com
     * @throws IOException
     * @date 2016年2月12日 下午9:14:25
     */
    public static void main(String[] args) throws IOException {
        File fileTest = new File("test.txt");// 这里不是真的创建一个文件
        System.out.println("文件是否存在:" + fileTest.exists());
        if (!fileTest.exists()) {
            fileTest.createNewFile();// 这里才是创建文件
        }
        System.out.println("第二次检查文件是否存在:" + fileTest.exists());
        System.out.println("文件路径:" + fileTest.getAbsolutePath());
        FileOutputStream fos = new FileOutputStream(fileTest, true);// 文件输出字节流
        OutputStreamWriter osw = new OutputStreamWriter(fos);// 字节流向字符流转换 默认为UTF-8编码方式
        BufferedWriter bw = new BufferedWriter(osw);// 缓存字符输出流
        bw.write("Hello World,你好中国n");
        bw.append("Hello World,你好中国n");
        bw.flush(); // 刷新缓存,防止未写入文件
        bw.close(); // 流关闭
        osw.close(); // 流关闭
        fos.close(); // 流关闭
        System.out.println("写入完毕");
        FileInputStream pis = new FileInputStream(fileTest);
        InputStreamReader isr = new InputStreamReader(pis);
        BufferedReader br = new BufferedReader(isr);
        String line = br.readLine();// 先读取一行
        while (line != null) { // 如果不为空继续读取直到为Null
            System.out.println(line);
            line = br.readLine();
        }
        br.close();
        isr.close();
        pis.close();
    }
}
package com.sunhaojie.learntest.twelfth;
 
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
 
/**
 * 
 * @ClassName SocketServerTest
 * @Description 服务器端测试类
 *
 * @author sunhaojie 3113751575@qq.com
 * @date 2016年2月12日 下午10:53:45
 */
public class SocketServerTest {
    @SuppressWarnings("static-access")
    public static void main(String[] args) throws IOException {
        ServerSocket serverSocket = new ServerSocket(8080);
        System.out.println("监听IP:" + serverSocket.getInetAddress().getLocalHost().getHostAddress() + "; 监听端口:"
                + serverSocket.getLocalPort());
        Socket acceptSocket = serverSocket.accept();
        InputStream inputStream = acceptSocket.getInputStream();
 
        InputStreamReader isr = new InputStreamReader(inputStream, "utf-8");
        BufferedReader br = new BufferedReader(isr);
 
        String line = null;
        while ((line = br.readLine()) != null) {
            System.out.println("客户输入:" + line);
        }
        br.close();
        isr.close();
 
        serverSocket.close();
        System.out.println("输出结束");
    }
}
package com.sunhaojie.learntest.twelfth;
 
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.net.UnknownHostException;
 
/**
 * 
 * @ClassName SocketClientTest
 * @Description 测试端输出类
 *
 * @author sunhaojie 3113751575@qq.com
 * @date 2016年2月12日 下午10:54:03
 */
public class SocketClientTest {
    public static void main(String[] args) throws UnknownHostException,
            IOException {
        Socket socket = new Socket("127.0.0.1", 8080);
        OutputStream outputStream = socket.getOutputStream();
        BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(
                outputStream));
 
        writer.write("hin");
        writer.flush();
        writer.write("my name is lilein");
        writer.flush();
        writer.write("byen");
        writer.flush();
        writer.close();
        outputStream.close();
 
        socket.close();
    }
}

建议继续学习:

  1. 避免输入    (阅读:2309)
  2. 触摸屏输入的交互设计    (阅读:2302)
  3. PHP里模拟$_PUT    (阅读:1967)
  4. [Java基础教程]第十三章-Java多线程    (阅读:2347)
  5. [Java基础教程]第十一章-Java类和对象    (阅读:2262)
QQ技术交流群:445447336,欢迎加入!
扫一扫订阅我的微信号:IT技术博客大学习
© 2009 - 2024 by blogread.cn 微博:@IT技术博客大学习

京ICP备15002552号-1