www.91084.com

GVKun编程网logo

CipherInputStream和CipherOutputStream不生成文件(inputstream fileinputstream)

12

以上就是给各位分享CipherInputStream和CipherOutputStream不生成文件,其中也会对inputstreamfileinputstream进行解释,同时本文还将给你拓展(转)

以上就是给各位分享CipherInputStream和CipherOutputStream不生成文件,其中也会对inputstream fileinputstream进行解释,同时本文还将给你拓展(转)InPutStream和OutPutStream的使用 InPutStream是读 OutPutStream是写、(转)java的InputStream和OutputStream的理解、013-java中的IO操作-InputStream/Reader、OutputStream/Writer、android-将字节从FileInputStream复制到CipherOutputStream(反之亦然)非常慢等相关知识,如果能碰巧解决你现在面临的问题,别忘了关注本站,现在开始吧!

本文目录一览:

CipherInputStream和CipherOutputStream不生成文件(inputstream fileinputstream)

CipherInputStream和CipherOutputStream不生成文件(inputstream fileinputstream)

我有以下代码。但是,文件b.xlsxc.xlsx是0字节。为什么CipherOuputSteam不工作?

public static void main(String[] args) throws Exception {    KeyPair keys = KeyPairGenerator.getInstance("RSA").generateKeyPair();    Cipher cipher = Cipher.getInstance("RSA");    cipher.init(Cipher.ENCRYPT_MODE, keys.getPublic());    FileInputStream fis;    FileOutputStream fos;    CipherOutputStream  cos;    fis = new FileInputStream("C:/temp/a.xlsx");    fos = new FileOutputStream("C:/temp/b.xlsx");    cos = new CipherOutputStream (fos, cipher);    byte[] block = new byte[8];    int i;    while ((i = fis.read(block)) != -1) {        cos.write(block, 0, i);    }    cos.close();    fos.close();    cipher.init(Cipher.DECRYPT_MODE, keys.getPrivate());    CipherInputStream cis1, cis2;    fis = new FileInputStream("c:/temp/b.xlsx");    CipherInputStream cis = new CipherInputStream(fis, cipher);    fos = new FileOutputStream("c:/temp/c.xlsx");    while ((i = cis.read(block)) != -1) {        fos.write(block, 0, i);    }    fos.close();    fis.close();    cis.close();}

答案1

小编典典

问题出在您的用法上-这是不正确的,并且在实现中CipherOutputStream掩盖了一个非常重要的异常-
IllegalBlockSizeException

问题是您不能使用RSA密钥来加密长度超过密钥大小(示例中为128字节)的数据。您应该对大数据块使用对称加密算法,例如 AES

如果您出于某种原因(例如安全传输数据)使用非对称密钥-
您可以在此SO答案中找到一个很好的示例。

(转)InPutStream和OutPutStream的使用 InPutStream是读 OutPutStream是写

(转)InPutStream和OutPutStream的使用 InPutStream是读 OutPutStream是写

 

 

https://blog.csdn.net/qq_38363025/article/details/79626884

 

InPutStream是读

OutPutStream是写

 

InPutStream的实现

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
 
public class TestFileInPutStream {
    public static void main(String[] args) {
        try {
            File file = new File("D:/test/testIO.java");
            // 如果文件存在,读取文件中的内容,并在控制台输出
            if (file.exists()) {
                InputStream in = new FileInputStream(file);
                int a = 0;
                while ((a = in.read()) != -1) {
                    System.out.print((char) a);
                }
                in.close();
 
            } else {
                // 如果文件不存在返回文件不存在
                System.out.println("文件不存在");
 
            }
 
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
 
    }
}

在D盘已经存在testIO文件如下:

 

 

 OutPutStream的实现

先读取testIO.java里的内容然后在写到testIOO.txt里面

 

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
 
public class TestOutPutStream {
    private static InputStream in;
    private static OutputStream out;
    public static void main(String[] args) {
        
        try {
            in = new FileInputStream("D:/test/testIO.java");
            if(in == null){
                //原文件不存在
                System.out.println("原文件不存在");
            }else{
                //原文件存在,判断目标文件是否存在
                File file = new File("D:/test/testIOO.txt");
                if(!file.exists()){
                    //目标文件不存在,创建目标文件
                    file.getParentFile().mkdirs();
                    file.createNewFile();
                }
                //将原文件内容读取到目标文件
                out = new FileOutputStream(file);
                int a = 0;
                while((a = in.read()) != -1){
                    out.write(a);
                }
                
            }
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }finally{
            //流关闭
            try {
                if(in != null){
                    in.close();
                }
                if(out != null){
                    out.close();
                }
                
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
}

D盘中原文件存在,在D盘中创建了目标文件

注意:在判断原文件是否存在时,直接判断字节流文件对象是否存在

(转)java的InputStream和OutputStream的理解

(转)java的InputStream和OutputStream的理解

1、在java中stream代表一种数据流(源),javaio的底层数据元,---(想像成水龙头)
2、任何有能力产生数据流(源)的javaio对象就可以看作是一个InputStream对象
既然它能产生出数据,我们就可以将数据取出,java对封装的通用方法就read()方法了--(出水龙头)
3、任何有能力接收数据源(流)的javaio对象我们就可以看作是一个OutputStream对象
同样,它能接收数据,我们就可以调用它的write方法,来让它接收数据--(进水龙头了,呵呵)
4、当然,我们可以在Inputstream和OutputStream数据源的基础上,从实际需要触发,
来重新封装出不同性能机制的输入、输出流了,java.io包中提供了很丰富的输入、输出流对象,如:
基于字节流的stream:
DataOutputStream----DataInputStream:
FileOutputStream-----FileInputStream:
.............等,可以用InputStream和OutputStream从JDK文档查阅
基于字符流的stream(典型的以write和reader来标识的):
FileWriter---FileReader:
StringWriter---StringReader:
.........等,你自己可以用Writer和Reader从JDK文档里头查看说明
stream应该是水龙头里的水资源,
InputStream:是一个出水龙头(把水封装在里头)的一个实物对象,该对象的read方法呢,就想成这个
出水龙头这一机制对象的开关钮,你read或openStream(其他对象包容InputStream对象的对象方法)一下呢,就等于打开了出水龙头的按钮,水就出来了,里头封装的水是什么性质的呢,你就用相应的容器来装,如string或byte[].....
OutputStream:你就在InputStream基础上反着想就ok了 
-------------------------------------------------------------------------------------------------------------------------
OutputStream
(1)输出数据
   void write(int b)往流中写一个字节b
   void write(byte b[])往流中写一个字节数组b
   void write(byte b[],int off,int len)把字节数组b中从下标off开始,长度为len的字节写入流中
 (2)
   flush()刷空输出流,并输出所有被缓存的字节
   由于某些流支持缓存功能,该方法将把缓存中所有内容强制输出到流中。
(3)关闭流
   close()流操作完毕后必须关闭。
------------------------------------------------------------------------------------------------------------------------
InputStream
(1)从流中读取数据
   int read() 读取一个字节,返回值为所读得字节
   int read(byte b[]) 读取多个字节,放置到字节数组b中,通常读取的字节数量为b的长度,返回值为实际独取的
 字节的数量。
   int read(byte b[] ,int off,int len)读取len个字节,放置到以下标off开始字节数组b中,返回值为实际
 读取的字节的数量。
   int available() 返回值为流中尚未读取的字节的数量。
   long skip(long n);读指针跳过n个字节不读,返回值为实际跳过的字节数量
(2)关闭流
   close() 流操作完毕后必须关闭
(3)使用输入流中的标记
   void mark(int readlimit)纪录当前指针的所在位置.readlimit表示读指针读出的readlimit个字节后 所标记的指针位置才实效。
   void reset() 把读指针重新指向用mark方法所记录的位置
   boolean markSupported() 当前的流是否支持读指针的记录功能。
-----------------------------------------------------------------------------------------------------------------------

Java IO通过Stream(流)来实现。关于流,可以理解为是一种“数据的管道”。管道中流动的东西可以是基于字节,也可以是基于字符的等。就好像管道里面可以流动水,也可以流动石油一样。

而对应于流还有一个概念:输入、输出设备。这些设备可以是磁盘文件、键盘(输入设备)、显示器(输出设备)、打印机(输出设备)、网络套接字等等。

下面,我们就来了解“流”。

Java中定义了两种类型的流:字节型,和字符型。

字节流:处理字节的输入和输出。包括读写二进制数据等方面的内容。

字符流:处理字符的输入和输出。他采用的是Unicode编码,可以实现国际化。使用字符流的另外一个好处就是:字符流比字节流更有效率。

字节流:

字节流包含两个顶层抽象类:InputStream和OutputStream。

1:字节流的两个顶层类是抽象类,分别是:InputStream和OutputStream。

2:每个抽象类都有子类来实现具体的功能,处理不同的设备的输入和输  出。

下面简单介绍字节流的几个常用子类:

字节流类功能简单介绍

DataInputStream包含了读取Java标准数据类型的输入流

DataOutputStream包含了写Java标准数据类型的输出流

ByteArrayInputStream从字节数组读取的输入流

ByteArrayOutputStream写入字节数组的输出流

FileInputStream从文件读入的输入流

FileOutputStream写入文件的输出流

PrintStream包含最常见的Print()和Println()的输出流

PushbackInputStream返回一个字节到输入流,主要用于编译器的实现

PipedInputStream输出管道

PipedOutputStream输入管道

SequenceInputStream将n个输入流联合起来,一个接一个按一定顺序读取

RandomAccessFile随机访问文件

BufferInputStream缓冲输入流

BufferOutputStream缓冲输出流

FilterInputStream实现了InputStream Interface

FilterOutputStream实现了OutputStream Interface

InputStream抽象类,描述流的输入

OutputStream抽象类,描述流的输入

抽象类InputStream和OutpurStream定义了实用的方法,其中最主要的是read()和write()。这两个方法在InputStream和OutputStream中声明为抽象方法,由子流类overwrite实现。

2:每个抽象类都有子类来实现具体的功能,处理不同的设备的输入和输  出。

下面简单介绍字节流的几个常用子类:

DataInputStream包含了读取Java标准数据类型的输入流

DataOutputStream包含了写Java标准数据类型的输出流

ByteArrayInputStream从字节数组读取的输入流

ByteArrayOutputStream写入字节数组的输出流

FileInputStream从文件读入的输入流

FileOutputStream写入文件的输出流

PrintStream包含最常见的Print()和Println()的输出流

PushbackInputStream返回一个字节到输入流,主要用于编译器的实现

PipedInputStream输出管道

PipedOutputStream输入管道

SequenceInputStream将n个输入流联合起来,一个接一个按一定顺序读取

RandomAccessFile随机访问文件

BufferInputStream缓冲输入流

BufferOutputStream缓冲输出流

FilterInputStream实现了InputStream Interface

FilterOutputStream实现了OutputStream Interface

InputStream抽象类,描述流的输入

OutputStream抽象类,描述流的输入

抽象类InputStream和OutpurStream定义了实用的方法,其中最主要的是read()和write()。这两个方法在InputStream和OutputStream中声明为抽象方法,由子流类overwrite实现。


013-java中的IO操作-InputStream/Reader、OutputStream/Writer

013-java中的IO操作-InputStream/Reader、OutputStream/Writer

一、概述

  IO流用来处理设备之间的数据传输,上传文件和下载文件,Java对数据的操作是通过流的方式,Java用于操作流的对象都在IO包中。

  流是一组有顺序的,有起点和终点的字节集合,是对数据传输的总称或抽象。即数据在两设备间的传输称为流,流的本质是数据传输,根据数据传输特性将流抽象为各种类,方便更直观的进行数据操作。

  注:java把所有的传统的流类型都放到在java.io包下,用于实现输入和输出功能。

1.1、IO流分类

  按照流的不同方向分为:输入流和输出流,

    凡是含有in的,都可理解为输入流,输入流即从文件读取到程序,只能从中读取数据,而不能向其写入数据,

    凡是含有out的,都可以理解为输出流,输出流即从程序输出到文件,只能向其写入数据,而不能向其读取数据。

    输入,输出都是从程序运行所在的内存的角度来划分的。

  按照实现功能不同可以分为:节点流和处理流。

    可以从/向一个特定的IO设备(如磁盘,网络)读/写数据的流,称为节点流。节点流也被称为低级流。

    处理流则用于对一个已存在的流进行连接和封装,通过封装后的流来实现数据的读/写功能。处理流也被称为高级流。

  按照数据类型【单位分】:字节流:InputStream(字节输入流)、OutputStream(字节输出流);字符流:Reader(字符输入流)、Writer(字符输出流);因为数据编码的不同,而有了对字符进行高效操作的流对象。本质其实就是基于字节流读取时,去查了指定的码表。

1.1.1、字节流与字符流区别

  本质区别只有一个:字节流是原生的操作,而字符流是经过处理后的操作。

  在进行网络数据传输、磁盘数据保存所保存所支持的数据类型只有:字节。

  而所有磁盘中的数据必须先读取到内存后才能进行操作,而内存中会帮助我们把字节变为字符。字符更加适合处理中文。  

  读写单位不同:字节流以字节(8bit)为单位,字符流以字符为单位,根据码表映射字符,一次可能读多个字节。

  处理对象不同:字节流能处理所有类型的数据(如图片、avi等),而字符流只能处理字符类型的数据。

  字节流在操作的时候本身是不会用到缓冲区的,是文件本身的直接操作的;而字符流在操作的时候下后是会用到缓冲区的,是通过缓冲区来操作文件,

  结论:优先选用字节流。首先因为硬盘上的所有文件都是以字节的形式进行传输或者保存的,包括图片等内容。

  首先必须要明确一点,通过任何终端(网络、文件)读取或者输出的数据都一定是字节,字符是经过内存处理后的数据。

    字符输入:字节(磁盘)–> 自动转换为 –>字符(内存);

    字符输出:字符(内存)–> 自动转换为–>字节(磁盘);

  在利用字符流输出的时候,所有的内容实际上都只是输出到了缓冲区中(内存)。在使用close()方法关闭的时候会将我们缓冲区的数据进行输出,如果没有关闭,那么就将无法进行输出,此时可以利用flush()方法进行强制的输出。

  字符使用到了缓冲区,而字节流没有使用到缓冲区。

  如果处理中文使用字符流,其他的任何数据都使用字节流。

1.2、操作流程

  1、创建File类对象 ,主要是指明要操作的文件路径;
  2、根据字节流或字符流的子类实例化父类对象 ;
  3、进行数据的读取或写入操作;
  4、关闭流(close());

  注意:对于IO操作属于资源处理,所有的资源处理操作(IO操作、数据库操作、网络)最后必须要进行关闭。

1.3、流原理浅析

  java Io流共涉及40多个类,这些类看上去很杂乱,但实际上很有规则,而且彼此之间存在非常紧密的联系, Java Io流的40多个类都是从如下4个抽象类基类中派生出来的。

    InputStream/Reader: 所有的输入流的基类,前者是字节输入流,后者是字符输入流。

    OutputStream/Writer: 所有输出流的基类,前者是字节输出流,后者是字符输出流。

  对于InputStream和Reader而言,它们把输入设备抽象成为一个”水管“,这个水管的每个“水滴”依次排列,如图15.5所示: 

  字节流和字符流的处理方式其实很相似,只是它们处理的输入/输出单位不同而已。输入流使用隐式的记录指针来表示当前正准备从哪个“水滴”开始读取,每当程序从InputStream或者Reader里面取出一个或者多个“水滴”后,记录指针自定向后移动;除此之外,InputStream和Reader里面都提供了一些方法来控制记录指针的移动。

  

  对于OutputStream和Writer而言,它们同样把输出设备抽象成一个”水管“,只是这个水管里面没有任何水滴,如图15.6所示:

  当执行输出时,程序相当于依次把“水滴”放入到输出流的水管中,输出流同样采用隐示指针来标识当前水滴即将放入的位置,每当程序向OutputStream或者Writer里面输出一个或者多个水滴后,记录指针自动向后移动。 

     

  以上显示了java Io的基本概念模型,除此之外,Java的处理流模型则体现了Java输入和输出流设计的灵活性。处理流的功能主要体现在以下两个方面。

  • 性能的提高:主要以增加缓冲的方式来提供输入和输出的效率。
  • 操作的便捷:处理流可能提供了一系列便捷的方法来一次输入和输出大批量的内容,而不是输入/输出一个或者多个“水滴”。

  处理流可以“嫁接”在任何已存在的流的基础之上,这就允许Java应用程序采用相同的代码,透明的方式来访问不同的输入和输出设备的数据流。图15.7显示了处理流的模型。

    

1.4、java输入/输出流体系中常用的流的分类表  

分类 字节输入流 字节输出流 字符输入流 字符输出流
抽象基类 InputStream OutputStream Reader Writer
访问文件 FileInputStream FileOutputStream FileReader FileWriter
访问数组 ByteArrayInputStream ByteArrayOutputStream CharArrayReader CharArrayWriter
访问管道 PipedInputStream PipedOutputStream PipedReader PipedWriter
访问字符串     StringReader StringWriter
缓冲流 BufferedInputStream BufferedOutputStream BufferedReader BufferedWriter
转换流     InputStreamReader OutputStreamWriter
对象流 ObjectInputStream ObjectOutputStream    
抽象基类 FilterInputStream FilterOutputStream FilterReader FilterWriter
打印流   PrintStream   PrintWriter
推回输入流 PushbackInputStream   PushbackReader  
特殊流 DataInputStream DataOutputStream    

注:表中粗体字所标出的类代表节点流,必须直接与指定的物理节点关联:斜体字标出的类代表抽象基类,无法直接创建实例。

二、常用IO流基础用法

2.1、 IO体系的基类(InputStream/Reader,OutputStream/Writer)

  字节流和字符流的操作方式基本一致,只是操作的数据单元不同——字节流的操作单元是字节,字符流的操作单元是字符。

2.1.1、InputStream和Reader输入流

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

  a、在InputStream里面包含如下3个方法。

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

  b、在Reader中包含如下3个方法。

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

  直到read(char[] chuf)或者read(byte[] b)方法返回-1,即表明到了输入流的结束点。 

  c、InputStream和Reader提供的一些移动指针的方法:

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

2.1.2、OutputStream和Writer输出流

  两个流都提供了如下三个方法:

  • void write(int c); 将指定的字节/字符输出到输出流中,其中c即可以代表字节,也可以代表字符。
  • void write(byte[]/char[] buf); 将字节数组/字符数组中的数据输出到指定输出流中。
  • void write(byte[]/char[] buf, int off,int len ); 将字节数组/字符数组中从off位置开始,长度为len的字节/字符输出到输出流中。

  因为字符流直接以字符作为操作单位,所以Writer可以用字符串来代替字符数组,即以String对象作为参数。Writer里面还包含如下两个方法。

  • void write(String str); 将str字符串里包含的字符输出到指定输出流中。
  • void write (String str, int off, int len); 将str字符串里面从off位置开始,长度为len的字符输出到指定输出流中。

2.2、使用

以下包含内容:

  2.2.1、基础文件流【FileInputStream/FileReader ,FileOutputStream/FileWriter】

  2.2.2、缓冲流【BufferedInputStream/BufferedReader, BufferedOutputStream/BufferedWriter】

  2.2.3、转换流的使用(InputStreamReader/OutputStreamWriter)

  2.3.4、对象流的使用(ObjectInputStream/ObjectOutputStream)

  2.3.5、字节数组内存流【ByteArrayInputStream、ByteArrayOutputStream

  2.3.6、打印流【PrintStream、PrintWriter】

  2.3.7、随机访问流【RandomAccessFile】

  2.3.8、合并流【SequenceInputStream】  

  2.3.9、数据流【DataInputStream、DataOutputStream】

  2.3.10、管道流【PipedInputStream(字节输入流),PipedOutStream(字节输出流),PipedReader(字符输入流),PipedWriter(字符输出流)】

  2.3.11、异步流【NIO】

2.2.1、基础文件流【FileInputStream/FileReader ,FileOutputStream/FileWriter】

  参看代码:common 的 common-iostream

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

  注: 使用java的io流执行输出时,不要忘记关闭输出流,关闭输出流除了可以保证流的物理资源被回收之外,可能还可以将输出流缓冲区中的数据flush到物理节点中里(因为在执行close()方法之前,自动执行输出流的flush()方法)。java很多输出流默认都提供了缓存功能,其实我们没有必要刻意去记忆哪些流有缓存功能,哪些流没有,只有正常关闭所有的输出流即可保证程序正常。

2.2.2、缓冲流【BufferedInputStream/BufferedReader, BufferedOutputStream/BufferedWriter】

  参看代码:common 的 common-iostream

  注意:当我们使用处理流套接到节点流上的使用的时候,只需要关闭最上层的处理就可以了。java会自动帮我们关闭下层的节点流。

2.2.3、转换流的使用(InputStreamReader/OutputStreamWriter)

  java使用System.in代表输入。即键盘输入,但这个标准输入流是InputStream类的实例,使用不太方便,而且键盘输入内容都是文本内容,所以可以使用InputStreamReader将其包装成BufferedReader,利用BufferedReader的readLine()方法可以一次读取一行内容

public class InputStreamReaderDemo {
    public static void main(String[] args) throws IOException {
        try {
            // 将System.in对象转化为Reader对象
            InputStreamReader reader = new InputStreamReader(System.in);
            //将普通的Reader包装成BufferedReader
            BufferedReader bufferedReader = new BufferedReader(reader);
            String buffer = null;
            while ((buffer = bufferedReader.readLine()) != null) {
                // 如果读取到的字符串为“exit”,则程序退出
                if (buffer.equals("exit")) {
                    System.exit(1);
                }
                //打印读取的内容
                System.out.print("输入内容:" + buffer);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
        }
    }
}

  上面程序将System.in包装成BufferedReader,BufferedReader流具有缓存功能,它可以一次读取一行文本——以换行符为标志,如果它没有读到换行符,则程序堵塞。等到读到换行符为止。运行上面程序可以发现这个特征,当我们在控制台执行输入时,只有按下回车键,程序才会打印出刚刚输入的内容。

2.3.4、对象流的使用(ObjectInputStream/ObjectOutputStream)

  参看代码:common 的 common-iostream中ObjectStreamDemo

  注:ObjectInputStream(对象输入流)继承于InputStream,ObjectOutputStream(对象输出流)继承于OutputStream。

  对象流是将对象的基本数据和图形实现持久存储。ObjectOutputStream实际是在对流进行序列化操作,ObjectInputStream实际是在对流进行反序列化操作,要实现序列化,必须实现Serializable接口,否则是无法进行序列化和反序列化的,

  如果对象中的属性加了transient和static关键字的话,则该属性不会被序列化。

  常用的方法是:readObject(),从ObjectInputStream读取对象;writeObject(Object obj),将指定的对象写入ObjecctOutputStream;close(),关闭该流

2.3.5、字节数组内存流【ByteArrayInputStream、ByteArrayOutputStream

  参看代码:common 的 common-iostream   

  ByteArrayInputStream(内存输入流)继承于InputStream,ByteArrayOutputStream(内存输出流)继承于OutputStream。

  内存流是关不掉的,一般用来存放一些临时性的数据,理论值是内存大小。

2.3.6、打印流【PrintStream、PrintWriter】

  参看代码:common 的 common-iostream中PrintStreamAndWriterDemo 

2.3.7、随机访问流【RandomAccessFile】

  参看代码:common 的 common-iostream中RandomAccessFileDemo

2.3.8、合并流【SequenceInputStream】

  参看代码:common 的 common-iostream中SequenceInputStreamDemo

2.3.9、数据流【DataInputStream、DataOutputStream】

  DataOutputStream数据输出流允许应用程序将基本Java数据类型写到基础输出流中,而DataInputStream数据输入流允许应用程序以机器无关的方式从底层输入流中读取基本的Java类型.

  参看代码:common 的 common-iostream中DataStreamDemo

2.3.10、管道流【PipedInputStream(字节输入流),PipedOutStream(字节输出流),PipedReader(字符输入流),PipedWriter(字符输出流)】

  在java中,PipedOutputStreamPipedInputStream分别是管道输出流和管道输入流。

  它们的作用是让多线程可以通过管道进行线程间的通讯。在使用管道通信时,必须将PipedOutputStream和PipedInputStream配套使用。

  使用管道通信时,大致的流程是:我们在线程A中向PipedOutputStream中写入数据,这些数据会自动的发送到与PipedOutputStream对应的PipedInputStream中,进而存储在PipedInputStream的缓冲中;此时,线程B通过读取PipedInputStream中的数据。就可以实现,线程A和线程B的通信。  

  参看代码:common 的 common-iostream中pipedstream

2.3.11、异步流【NIO】

  io流大体分为BIO,AIO,NIO,常用的基本就是BIO,也就是之前文章所介绍的那些,接下来我们来大概了解一下NIO。

  传统io是靠字节或字符来传输,nio是靠块传输,也就是一个一个的buffer速度相对于较快。传统io是阻塞型io,nio是非阻塞型io。多适用于进行流畅的网络读写操作。

  参看代码:common 的 common-iostream中NIODemo

 

  

2.4、何为NIO,和传统Io有何区别

  我们使用InputStream从输入流中读取数据时,如果没有读取到有效的数据,程序将在此处阻塞该线程的执行。其实传统的输入里和输出流都是阻塞式的进行输入和输出。 不仅如此,传统的输入流、输出流都是通过字节的移动来处理的(即使我们不直接处理字节流,但底层实现还是依赖于字节处理),也就是说,面向流的输入和输出一次只能处理一个字节,因此面向流的输入和输出系统效率通常不高。 

  从JDk1.4开始,java提供了一系列改进的输入和输出处理的新功能,这些功能被统称为新IO(NIO)。新增了许多用于处理输入和输出的类,这些类都被放在java.nio包及其子包下,并且对原io的很多类都以NIO为基础进行了改写。新增了满足NIO的功能。 

  NIO采用了内存映射对象的方式来处理输入和输出,NIO将文件或者文件的一块区域映射到内存中,这样就可以像访问内存一样来访问文件了。通过这种方式来进行输入/输出比传统的输入和输出要快的多。

  JDk1.4使用NIO改写了传统Io后,传统Io的读写速度和NIO差不了太多。 

2.5、文件拷贝

  参看代码:common 的 common-iostream中CopyFileDemo

  1024字节数组复制并用了缓冲流 的方式效率最高  

2.6、小结

  • 如果是操作二进制文件那我们就使用字节流,如果操作的是文本文件那我们就使用字符流。
  • 尽可能的多使用处理流,这会使我们的代码更加灵活,复用性更好。

 

 

 

 

 

 

 

 

地方

android-将字节从FileInputStream复制到CipherOutputStream(反之亦然)非常慢

android-将字节从FileInputStream复制到CipherOutputStream(反之亦然)非常慢

我一直在遵循教程“ How do I encrypt and decrypt files using DES?”向现有的Android 4应用添加简单的文件加密.

一切工作正常,除了加密和解密非常非常慢.

以下两种方法几乎是完整的教程:

public static void encryptOrDecrypt(String key, int mode, InputStream is, OutputStream os) throws Throwable {
    DESKeySpec dks = new DESKeySpec(key.getBytes());
    SecretKeyFactory skf = SecretKeyFactory.getInstance("DES");
    SecretKey desKey = skf.generateSecret(dks);
    Cipher cipher = Cipher.getInstance("DES"); // DES/ECB/PKCS5Padding for SunJCE

    if (mode == Cipher.ENCRYPT_MODE) {
        cipher.init(Cipher.ENCRYPT_MODE, desKey);
        CipherInputStream cis = new CipherInputStream(is, cipher);
        docopy(cis, os);
    } else if (mode == Cipher.DECRYPT_MODE) {
        cipher.init(Cipher.DECRYPT_MODE, desKey);
        CipherOutputStream cos = new CipherOutputStream(os, cipher);
        docopy(is, cos);
    }
}

public static void docopy(InputStream is, OutputStream os) throws IOException {
    byte[] bytes = new byte[64];
    int numBytes;

    // Why is this taking so long?
    while ((numBytes = is.read(bytes)) != -1) {
        os.write(bytes, 0, numBytes);
    }

    os.flush();
    os.close();
    is.close();
}

非常简单和基本,但是解密/加密1 MB文件大约需要20-30秒.详细地说,是while循环在两个流之间复制字节,这太慢了.

将byte []的大小更改为较大的值(如65536)以一次读取更多字节不会改变任何内容.我认为一次读取更多字节将加快处理速度,但事实并非如此.

在没有加密的情况下在“正常”流之间复制数据不会花费很长时间.真的是这种昂贵的加密吗?我已经在其他平台上使用了类似的加密,而这样的延迟从来都不是问题.

本教程使用DES,但将算法更改为其他内容,例如AES也不更改任何内容.

有什么想法可以加快速度吗?

解决方法:

我基本上在运行Android 4.4.4的Google LG Nexus 5上进行了一些实验,使用您的代码并加密了一个1000000(百万)字节的文件,并读取了/ sdcard文件系统的内容.

no crypt 1421 ms
AES ECB mode 2577 ms
DES ECB 3214

接下来,我稍微修改了您的代码以使用BufferedInputStream和@L_301_2@

no crypt 88 ms
AES ECB mode 855 ms
DES ECB mode 1419 MS

这表明时序对缓冲很敏感,并且AES比DES快.

提供程序名称为“ AndroidOpenSSL”

关于CipherInputStream和CipherOutputStream不生成文件inputstream fileinputstream的问题就给大家分享到这里,感谢你花时间阅读本站内容,更多关于(转)InPutStream和OutPutStream的使用 InPutStream是读 OutPutStream是写、(转)java的InputStream和OutputStream的理解、013-java中的IO操作-InputStream/Reader、OutputStream/Writer、android-将字节从FileInputStream复制到CipherOutputStream(反之亦然)非常慢等相关知识的信息别忘了在本站进行查找喔。

本文标签: