io 5.0 InputStream 和 Reader

InputStream和Reader

InputStream和Reader是所有输入流的抽象基类,本身并不能创建实例来执行输入,但它们将成为所有输入流的模板,所以它们的方法是所有输入流都可使用的方法。

idea 查看他们的 父子关系
在这里插入图片描述
Reader 的子类
在这里插入图片描述
InputStream 的子类会更多。

在InputStream里包含如下三个方法。

  • int read():从输入流中读取单个字节(相当于从水管中取出一滴水),返回所读取的字节数据(字节数据可直接转换为int类型)。
  • int read(byte[] b):从输入流中最多读取b.length个字节的数据,并将其存储在字节数组b中,返回实际读取的字节数。
  • int read(byte[] b, int off, int len):从输入流中最多读取len个字节的数据,并将其存储在数组b中,放入数组b中时,并不是从数组起点开始,而是从off位置开始,返回实际读取的字节数。

在Reader里包含如下三个方法。

  • int read():从输入流中读取单个字符
  • int read(char[] cbuf):从输入流中最多读取cbuf.length个字符的数据,并将其存储在字符数组cbuf中,返回实际读取的字符数。
  • int read(char[] cbuf, int off, int len):从输入流中最多读取len个字符的数据,并将其存储在字符数组cbuf中,放入数组cbuf中时,并不是从数组起点开始,而是从off位置开始,返回实际读取的字符数。

InputStream和Reader所提供的方法功能基本是一样的。

InputStream和Reader都是将输入数据抽象成水管,所以程序既可以通过read()方法每次读取一个“水滴”,也可以通过read(char[]
cbuf)或read(byte[] b)方法来读取多个“水滴”。

当使用数组作为read()方法的参数时,可以理解为使用一个“竹筒”到水管中取水。

read(char[]cbuf)方法中的数组可理解成一个“竹筒”,程序每次调用输入流的read(char[] cbuf)或read(byte[] b)方法,就相当于用“竹筒”从输入流中取出一筒“水滴”,程序得到“竹筒”里的“水滴”后,转换成相应的数据即可;

程序多次重复这个“取水”过程,直到read(char[] cbuf)或read(byte[] b)方法返回−1,即表明到了输入流的结束点
在这里插入图片描述

InputStream 和 Reader 都是抽象类,本身不能创建实例,但他们分别有一个可用于读取文件的输入流:

FileInputStream 和 FileReader

他们都是节点流------会直接和指定文件关联。

下面程序示范了使用 FileInputStream 来读取自身的效果

public class FileInputStreamTest {
    public static void main(String[] args) {
        FileInputStream in = null;
        try {
            // 在类文件右键获取路径
            in = new FileInputStream("src\\com\\rrz\\FileInputStreamTest.java");

            int read;
            while ((read = in.read()) > 0) {
                System.out.print((char) read);
            }

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                assert in != null;
                in.close();
            } catch (IOException e) {
                e.printStackTrace();
            }

        }

    }
}

在这里插入图片描述

public class FileInputStreamTest {
    public static void main(String[] args) {
        FileInputStream in = null;
        try {
            // 在类文件右键获取路径
            in = new FileInputStream("src\\com\\rrz\\FileInputStreamTest.java");

            int hasRead;
            byte[] bytes = new byte[1024];
            while ((hasRead = in.read(bytes)) > 0) {
                System.out.print(new String(bytes, 0, hasRead));
            }

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                assert in != null;
                in.close();
            } catch (IOException e) {
                e.printStackTrace();
            }

        }

    }
}

在这里插入图片描述

注意:上面程序创建了一个长度为 1024 的 字节数组来读取该文件,实际上该 java 源文件的长度还不到1024 字节,也就是说,程序只需要执行一次 read ()方法即可读取全部内容。但如果创建较小长度的字节数组,程序运行时在输出中文注释时可能出现乱码—这是因为本文件保存时采用的 GBK 编码方式,在这种方式下,每个中文字符占 2 字节,如果 read()方法读取时只读到了 半个中文字符,这将导致乱码。

上面程序最后使用了 fis.close()来关闭该文件输入流,与 JDBC 编程一样,程序里打开的文件 IO 资源不属于内存里的资源,垃圾回收机制无法回收该资源,所以应该显式关闭文件 IO 资源。java 7改写了所有的 IO 资源类,他们都实现了 AutoCloseable 接口,因此都可以通过自动关闭资源的 try 语句来关闭这些 IO 流。

public class FileReaderTest {
    public static void main(String[] args) {
        try (FileReader in = new FileReader("src\\com\\rrz\\FileReaderTest.java")) {
            int hasRead;
            char[] chars = new char[32];
            while ((hasRead = in.read(chars)) > 0) {
                System.out.print(new String(chars, 0, hasRead));
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

在这里插入图片描述

上面的FileReaderTest.java程序与前面的FileInputStreamTest.java并没有太大的不同,程序只是将字符数组的长度改为32,这意味着程序需要多次调用read()方法才可以完全读取输入流的全部数据。程序最后使用了自动关闭资源的try语句来关闭文件输入流,这样可以保证输入流一定会被关闭。
除此之外,InputStream和Reader还支持如下几个方法来移动记录指针。

  • void mark(int readAheadLimit):在记录指针当前位置记录一个标记(mark)。
  • boolean markSupported():判断此输入流是否支持mark()操作,即是否支持记录标记。
  • void reset():将此流的记录指针重新定位到上一次记录标记(mark)的位置。
  • long skip(long n):记录指针向前移动n个字节/字符。

上一节:流的概念模型
下一节:OutputStream 和 Writer

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
以下是使用Java代码实现采用HTTPS和TLS 1.2版本建立连接,并完成双向TLS认证(mTLS)的示例: ```java import java.io.BufferedReader; import java.io.InputStream; import java.io.InputStreamReader; import java.net.URL; import java.security.KeyStore; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.KeyManagerFactory; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLException; import javax.net.ssl.TrustManager; import javax.net.ssl.TrustManagerFactory; import javax.net.ssl.X509TrustManager; public class SSLExample { public static void main(String[] args) throws Exception { // Load client certificate and private key for mTLS String keyStorePath = "client.jks"; String keyStorePassword = "password"; String keyPassword = "password"; KeyStore keyStore = KeyStore.getInstance("JKS"); keyStore.load(SSLExample.class.getClassLoader().getResourceAsStream(keyStorePath), keyStorePassword.toCharArray()); KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); keyManagerFactory.init(keyStore, keyPassword.toCharArray()); // Load server truststore for server certificate verification String trustStorePath = "server.jks"; String trustStorePassword = "password"; KeyStore trustStore = KeyStore.getInstance("JKS"); trustStore.load(SSLExample.class.getClassLoader().getResourceAsStream(trustStorePath), trustStorePassword.toCharArray()); TrustManagerFactory trustManagerFactory = TrustManagerFactory .getInstance(TrustManagerFactory.getDefaultAlgorithm()); trustManagerFactory.init(trustStore); // Create SSL context with TLS 1.2 protocol and mTLS configuration SSLContext sslContext = SSLContext.getInstance("TLSv1.2"); sslContext.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), null); // Set default SSL context for HTTPS connection HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory()); // Create URL object for HTTPS endpoint URL url = new URL("https://example.com/api"); // Open HTTPS connection HttpsURLConnection connection = (HttpsURLConnection) url.openConnection(); // Set request method and headers connection.setRequestMethod("GET"); connection.setRequestProperty("User-Agent", "Mozilla/5.0"); // Get response from HTTPS endpoint try (InputStream inputStream = connection.getInputStream(); BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream))) { String line; while ((line = reader.readLine()) != null) { System.out.println(line); } } catch (SSLException e) { e.printStackTrace(); } finally { connection.disconnect(); } } // Trust manager to accept all server certificates private static final TrustManager[] TRUST_ALL_CERTIFICATES = new TrustManager[] { new X509TrustManager() { public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { // Do nothing } public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { // Do nothing } public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[0]; } } }; } ``` 在上面的示例中,我们使用了Java的`HttpsURLConnection`类来建立连接。我们首先加载客户端证书和私钥,并使用它们来创建`KeyManager`对象。然后,我们加载服务器信任库并使用它来创建`TrustManager`对象。接下来,我们使用这些`KeyManager`和`TrustManager`对象创建一个SSL上下文对象,该对象使用TLS 1.2协议并完成mTLS配置。最后,我们将默认的SSL上下文设置为HTTPS连接,并打开连接以向服务器发送请求。 在此示例中,我们还提供了一个`TrustManager`实现,它接受所有服务器证书。这不是一个好的做法,因为它会使您的应用程序容易受到中间人攻击。在实际生产环境中,您应该使用一个更安全的`TrustManager`实现,它会验证服务器证书并拒绝不受信任的证书。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值