概要
- I/OとはInput/Output、つまりデータ伝送時の入出力を意味し、入出力はメモリに対する相対的なものとなります。
- Java IO (入力/出力) ストリームは、Java がデータの読み取りと書き込みを処理するために使用する主要なコンポーネントです。
- 一般的な I|O メディアには次のものがあります。
- ファイル(入力|出力)
- ネットワーク(入力|出力)
- キーボード(出力)
- 表示(出力)
- 使用するシーン
- ファイルコピー(ファイル)
- ファイルのアップロードとダウンロード
- Excelのインポートとエクスポート
- ネットワークプログラム(チャットツール)でのデータ送信
分類
概要
Java のほとんどすべての IO 操作では、java.io パッケージの使用が必要です。ストリームは次のように分類できます。
- フローの方向によって分割 (入力プロセスと出力プロセスは通常、プログラムの観点から考慮されます)
- 入力ストリーム (入力)
- 出力
- ストリーム処理の種類に応じて
- バイト ストリーム (バイト): バイトはコンピュータの記憶容量の基本単位 (バイト)、1B=8b、バイナリで 8 ビットを占有します。
- 文字ストリーム (char): 文字は、テキストまたは記号の総称です。
注: バイト ストリームはバイナリ タイプのファイル (画像、ビデオ、オーディオ、圧縮ファイルなど) など、あらゆるタイプのファイルを読み取ることができますが、文字ストリームはテキスト タイプのファイルを読み取るために使用されます。
- 流れの働きに従って
- ノード フロー (入力ソースおよび出力ソースと直接対話する)
- 処理ストリーム (他のストリームをラップするストリーム: ラッピング ストリーム)
バイトストリーム (InputStream && OutputStream)
日常の開発プロセスで一般的に使用されるバイト ストリーム:
FileInputStream && FileOutputStream: ファイルのコピー/コピーの実装に一般的に使用されます。
BufferedInputStream && BufferedOutputStream: IO回数を減らし、読み取り効率を向上させるため
PrintStream: 標準バイト印刷出力ストリームである OutputStream から派生 (ログ フレームワークの実装原理)
ZipOutputStream && ZipInputStream: ファイル圧縮/ファイル解凍に使用されます
文字ストリーム (リーダー && ライター)
日常の開発プロセスで一般的に使用される文字フロー:
FileReader&&FileWriter:作用同じFileInputStream && FileOutputStream
BufferedReader&&BufferedWriter: 機能は BufferedInputStream && BufferedOutputStream と同じですが、同時に BufferedReader はテキストを 1 行ずつ読み取ってテキスト処理を容易にするメソッドを提供します。
拡張:バイト ストリームがあらゆるファイルを読み取れることはわかっていますが、なぜ文字ストリームを設計する必要があるのでしょうか?
- キャラクター ファイルの場合、最初にバイトとして転送し、次に文字に変換するため、時間がかかります。
- キャラクターファイルの場合、テキストが中国語の場合は文字化けしやすくなります。
デザインパターン
IO フローでは、次のようなさまざまな設計パターンが使用されます。
アダプターモード
アダプタ パターンを使用すると、インターフェイスの互換性がないために連携できないクラスを連携させることができます。
Java IOにおいて文字ストリームとバイトストリームの相互変換を実現するために、2つのアダプタクラスが設計されています。
入力ストリームリーダーと出力ストリームライター
InputStreamReader isr = new InputStreamReader(new FileInputStream(fileName), "UTF-8");
BufferedReader bufferedReader = new BufferedReader(isr);
デコレータパターン
デコレータ パターンは、既存のオブジェクトの機能を変更せずに、既存のオブジェクトに新しい機能を動的に付加できます。InputStream のサブクラスである FilterInputStream、OutputStream のサブクラスである FilterOutputStream、Reader のサブクラスである BufferedReader および FilterReader、および Writer のサブクラスである BufferedWriter、FilterWriter および PrintWriter は、すべて抽象装飾クラスです。サブクラスオブジェクトの機能が強化されました。
練習する
ZipOutputStream&&FileOutputStream&&FileInputStream はファイル圧縮を実装します
/**
* 功能: 通过ZipOutputStream压缩文件,最后返回压缩包
* @param files
* @param fileName
* @return
*/
public File zipFiles(File[] files,String fileName) {
File zipFile = null;
FileOutputStream fosZipFile = null;
ZipOutputStream zosZipFile = null; //压缩文件输出流
try {
zipFile = downloadAttachmentService.createFile("", fileName); //创建一个空的文件目录
fosZipFile = new FileOutputStream(zipFile); //以文件流从内存中输出
zosZipFile = new ZipOutputStream(fosZipFile); //以压缩流从内存中输出
for (File file : files) {
FileInputStream fis = new FileInputStream(file); //对每个文件创建输入流,读取文件到内存
ZipEntry zipEntry = new ZipEntry(file.getName()); //ZipEntry用来创建压缩文件
zosZipFile.putNextEntry(zipEntry); //加入需要压缩的文件
byte[] bytes = new byte[1024];
int length;
while((length = fis.read(bytes)) >= 0) { //读取文件到内存
zosZipFile.write(bytes, 0, length); //文件写入压缩流
}
fis.close();
}
} catch (IOException e) {
e.printStackTrace();
} finally { //关闭流
try {
zosZipFile.close();
fosZipFile.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return zipFile; //返回压缩包
}
/**
* @Title: createFile
* @Description: 创建下载目录文件
* @author Bierce
* @param rootPath
* @param filename
* @return
* @throws IOException
*/
public File createFile(String rootPath, String filename) throws IOException {
// Default root path
if (rootPath.isEmpty()) {
rootPath = "download-cache";
}
File fRoot = new File(rootPath);
if (!fRoot.exists() || !fRoot.isDirectory()) {
fRoot.mkdirs();
}
// job sub path
String uuid = UUID.randomUUID().toString();
String directoryJob = rootPath + File.separator + getClass().getSimpleName() + File.separator + uuid;//文件名称随机生成保证唯一
File dirJob = new File(directoryJob);
if (!dirJob.exists() || !dirJob.isDirectory()) {
dirJob.mkdirs();
}
String filePath = directoryJob + File.separator + filename;
File file = new File(filePath);
if (!file.exists()) {
file.createNewFile();
}
return file;
}
//-----------------扩展方法-文件名去重保证唯一-----------------
/**
* @Title: snFileName_noUIID
* @Description: 去除sn文件UUID以及解决sn文件名重复问题
* @author Bierce
* @return file
*/
public File snFileName_noUIID(String fileParentPath,String snFileName,File file){
//snFileName:完整文件名 sn-xx..UUID..xx.xlsx
//snFileName_delUIID: sn.xlsx
//snFileName_prefix: sn
//suffix:xlsx
//文件名:如sn.xlsx
String snFileName_delUIID = snFileName.substring(0,snFileName.length() - 42) + ".xlsx";//42是固定长度:UUID+.xlsx
String snFileName_prefix = snFileName.substring(0,snFileName.length() - 42);//文件前缀
String suffix = snFileName.substring(snFileName.lastIndexOf("."));//文件后缀:.xlsx
try {
file = new File(fileParentPath + snFileName_delUIID);//设置sn文件所在目录为计划交接文件目录下
int i = 1;
//对于同名SN文件情况重新命名
while(file.exists()) {//保证文件夹下不存在同名文件
String newFileName = snFileName_prefix + "(" + i + ")" + suffix;
String parentPath = file.getParent();
file = new File(parentPath + File.separator + newFileName);
i++;
}
file.createNewFile();//new File 只是创建了一个File对象,还需要调用createNewFile()方法才能实现文件的成功创建
} catch (Exception e) {
}
return file;
}