ファイル操作とIO

目次

編集 1. ファイルについて理解する

1. ファイルパス

2. その他の知識

2. Java でのファイルの操作

3. ファイル内容の読み書き

1、リーダー

2、入力ストリーム

3. 出力


1. 文書を理解する

 ファイルはハードディスクにデータを保存する方法であり、オペレーティング システムはハードディスクの詳細の一部をカプセル化するのに役立ちます。

ファイルに関連するいくつかのインターフェイスを理解するだけで済みます

ハード ドライブはデータの保存に使用されます。メモリに比べて、ハード ドライブは記憶容量が大きく、アクセス速度が遅く、コストが低く、永続的に保存できます。

オペレーティング システムは、「ファイル システム」などのモジュールを通じてハードディスクを管理します。

実際、私のコンピュータにはハード ドライブが 1 つしかありません。オペレーティング システムは、ファイル システムを通じてこのハード ドライブを複数のハード ドライブに抽象化できます。NTFS は Windows のファイル システムであり、ハード ドライブ データを整理するための特定の形式がその背後にあります。

 EXT4 は Linux 上の一般的なファイル システムです


1. ファイルパス

異なるファイル システムでも同様のファイル管理方法があります。

「N 分ツリー」ツリー構造は、ディレクトリとファイルによって形成されます。

D ドライブ - tmp - cat.jpg というルートを通じて、コンピュータ上にある唯一のファイルを検索/特定できます。これを「パス」と呼びます。

Windows では、/ または \ を使用して異なるディレクトリを区切ります。

ドライブレターで始まるパスは「絶対パス」とも呼ばれます。

絶対パスは、「このコンピュータ」から始まるファイルを検索するプロセスに相当します。

. または... で始まる接眼レンズは「絶対パス」と呼ばれます。

相対パスには「ベース ディレクトリ」/「作業ディレクトリ」が必要です。これは、このベースから開始してこのフォルダを検索する方法を示します。

D:をベースディレクトリとする場合 /tmp/cat.jpg D:tmpをベースディレクトリとする場合 /cat.jpg (.はカレントディレクトリを示します)

D:/tmp/111 をベースとした場合、..cat.jpg (.. はカレントディレクトリの上位ディレクトリを表します)

これも cat.jpg ファイルですが、ベース ディレクトリごとにパスが異なります。


2. その他の知識

ファイル システムに保存されているファイルは、次の 2 つの主要なカテゴリに分類できます。

1. テキストファイル

文字が保存される

例: utf-8 は大きなテーブルであり、このテーブル上のデータの組み合わせを文字と呼ぶことができます。

2. バイナリファイル

バイナリデータを保存します

ファイルがテキスト ファイルかバイナリ ファイルかどうかを確認するにはどうすればよいですか?

最も簡単な方法: メモ帳で直接開く

メモ帳はファイルを開くと、コード テーブル内の現在のデータをクエリしようとします。

開いて理解できる場合はテキストファイル、開いて理解できない場合はバイナリファイルです。


2. Java でのファイルの操作

その後のファイル操作、テキスト操作、バイナリ操作は異なります。

ファイル システム操作: ファイルの作成、ファイルの削除、ディレクトリの作成...

Javaでは、ファイル(ディレクトリを含む)の詳細を記述するためにjava.io.fileクラスを使用しないでください。

IO: 入力と出力。CPU の観点から入力と出力を見ていきます。

File オブジェクトを通じて特定のファイルを記述します。

File オブジェクトは、実際のファイルまたは存在しないファイルに対応できます。

施工方法:

2 番目の構築方法の文字列はパスを表し、絶対パスまたは相対パスを使用できます。

方法: 

オペレーティング システムの観点から見ると、ディレクトリもファイルです

オペレーティング システム ファイルはより広い概念であり、具体的にはさまざまな種類があります

1. 通常のファイル(よく見るファイル)

2. ディレクトリ ファイル (よく見られるフォルダー)

Windows では、ディレクトリ間の区切り文字は / または \ です。 

Linux および Mac では / のみがサポートされます

したがって、Windows 上でも、/ を使用してみてください。コード内のエスケープ文字と一致する必要があります。

コードを通してファイルの操作を感じることができます。 絶対パスを相対パスに変更すると、コードの実行結果が異なります。

 getAbsolutePath は、操作の結果である作業ディレクトリを現在のディレクトリに結合します。

idea でプログラムを実行する場合、作業ディレクトリはプロジェクトが配置されているディレクトリです。コマンド ラインでプログラムを実行する場合、作業ディレクトリはコマンド ラインが現在配置されているディレクトリです。プログラムが tomacat で実行されている場合は、作業ディレクトリは、tomcat の下の bin ディレクトリです。

この操作では例外がスローされる可能性があります

たとえば、現在書き込まれているパスは不正なパスです。

たとえば、現在作成されているファイルには、それが配置されているディレクトリ上で操作する権限がありません。

場合によっては、次のような機能を使用することもあります: 一時ファイル

プログラムの実行中に一時ファイルが作成され、プログラムの終了時に一時ファイルは自動的に削除されます。

Office などの多くの生産性向上ソフトウェアには一時ファイルを生成する機能があり、この一時ファイルは現在の編集の中間状態を自動的に保存します。

Word を使用するときに保存するのが嫌いな人もいます。一定期間使用した後、突然コンピュータがシャットダウンして電源が落ちます。保存していないデータは失われますか?

コンピュータを再起動します。先ほど異常シャットダウンされたため、一時ファイルは削除できません。まだ存在する moffice を起動すると、前回異常シャットダウンされたことがわかります。未保存を復元するかどうかを尋ねられます。以前の一時ファイルのデータ。 

 ディレクトリコードを作成します。

import java.io.File;
import java.io.FileReader;

public class Demo4 {
    public static void main(String[] args) {
        File file = new File("./test-dir");
        //mk -> make dir->directory
        //mkdir 一次只能创建一层目录,mkdirs 可以一次创建多层目录
        file.mkdir();
        //file.mkdirs();
    }
}

 ファイルの名前を変更すると、ファイルが移動される可能性もあります

import java.io.File;

//文件重命名
public class Demo5 {
    public static void main(String[] args) {
        File file = new File("./test.txt");
        File file2 = new File("./src/test2.txt");
        file.renameTo(file2);
    }
}

上記のファイル システム操作はすべて File クラスに基づいて完了します。

さらに、ファイルの内容に対する操作も必要です


3. ファイル内容の読み書き

1、リーダー

ファイルの内容は基本的にハードディスクから取得され、ハードディスクはオペレーティング システムによって管理されます。特定のプログラミング言語を使用してファイルを操作するには、基本的にシステムの API を呼び出す必要があります。 

異なるプログラミング言語でファイルを操作するための API は異なりますが、基本的な手順は同じです。

ファイル コンテンツの操作には 4 つの主要な手順があります。

1. ファイルを開きます

2. ファイルを閉じます

3. ファイルを読み取る

4. ファイルの書き込み

Java IO ストリームは比較的大規模なシステムであり、多くのクラスが関与しており、クラスごとに異なる特性がありますが、一般的に使用されるメソッドは似ています。

(1) 構築方法、オープンファイル

(2) closeメソッド、ファイルを閉じます

(3) InputStream または Read から派生した場合、read メソッドを使用してデータを読み取ることができます

(4) OutputStream または Writer から派生した場合は、write メソッドを使用してデータを書き込むことができます

 ファイルの読み取り操作:

 この操作は必要なリソースを解放するために非常に重要です

プロセスがファイルを開くことを許可するには、システムから特定のリソースを申請する必要があります (プロセスの PCB のファイル記述子テーブル内のエントリを占有します)。

解放しないと「ファイルリソースの漏洩」が発生し、非常に深刻な問題となります。

ファイル記述子テーブルは、長さが制限されたシーケンス テーブルとして理解でき、自動的には拡張されません。未使用のファイルを閉じずにファイルを開いたままにすると、ファイル記述子テーブルがいっぱいになり、それ以降新しいファイルを開くことができなくなります。わかった

上記の問題を回避するには、rewsourses で try を使用できます。

このとき、tryコードが実行されていれば自動的にcloseメソッドが呼び出されます。

上記の説明に従って、ファイル ストリーム内の任意のオブジェクトを閉じることができます。

char型の配列を一度に読み取る

 読み取られた内容はパラメータの cbuf 配列に格納されます。ここでのパラメータは出力パラメータに相当します。

読み取りにより、元々空だった配列はコンテンツで埋められます。

nは実際に読み取られた文字数を表します

これは 1024 という大きなスペースを与えるのと同じで、ファイルが十分に大きく 1024 を超える場合は、このスペースを埋めることができます。

ファイルが比較的小さい場合 (1024 未満)、ファイルのすべての内容が配列に入力されます (残りは空になります)。

戻り値 n は実際に読み取られた文字数を表します。

場合によっては、複数の小さなファイルを読み取って結合する必要がある場合がありますが、この方法を使用できます。

3 つのファイルがあり、各ファイルのサイズが 100 バイトであると仮定します。

 最終的なコードは次のとおりです。

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;

//Reader 的使用
public class Demo6 {
    public static void main(String[] args) throws IOException {
/*        //FileReder 的构造方法,可以填写一个路径(绝对路径和相对路径都可以),也可以写一个构造好了的 file 对象
        Reader reader = new FileReader("d:/test.txt");
        try {
            //中间的代码无论出现什么情况,close 都可以执行到
        }finally {
            //如果抛出异常或者 return ,close就都执行不到了
            reader.close();
        }*/

        //上述使用 finally 的方式能解决问题,但是不优雅
        //使用 try with resourses 是更好的解决方法
        try(Reader reader = new FileReader("d:/test.txt")){
            while(true){
                char buf[] = new char[1024];
                int n = reader.read(buf);
                if(n == -1){
                    //读到文件末尾了
                    break;
                }
                for(int i = 0;i < n;i++){
                    System.out.print(buf[i] + " ");
                }
            }
        }
    }
}

2、入力ストリーム

InputStream はバイト ストリームであり、その使用法は Reader と似ています。

バイト ストリームを使用してテキスト ファイルを開くこともできますが、このときに読み取る各バイトは完全な文字ではありません。

 一度に 1 バイトずつ読み取ります

 一度に複数のバイトを読み取り、この byte[] を埋めようとします

一度に数バイトを読み取り、配列の一部を埋めます

Java には char がありますが、ほとんど使用されず、主に String が使用されます。 

ここでは、いくつかの追加のツール クラスを使用して、バイト/文字 --> 文字列の変換を完了できます。

String 構築メソッドを直接使用して、char[] または byte[] から string への変換を完了することもできますが、それはより面倒です。

このツール クラスはスキャナーです。

オペレーティングシステムにおけるいわゆるファイルは広い概念であり、System.in は「標準入力」に相当する特殊なファイルであり、ハードディスク上の通常のファイルもファイルです。

その後、ネットワークプログラミングにおけるネットワークカード(ソケット)もファイルになりました

スキャナは全員を平等に扱い、現在読み取られているバイト データのみを変換しますが、データがどこから来たのかは気にしません。

ただし、Scanner はテキスト ファイルの読み取りにのみ使用され、バイナリ ファイルの読み取りには適していないことに注意してください。

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Scanner;

public class Demo8 {
    public static void main(String[] args) throws IOException {
        try(InputStream inputStream = new FileInputStream("d:/test.txt")){
            Scanner scanner = new Scanner(inputStream);
            //此时就是从 test.txt 这个文件中读取数据了
            String s = scanner.next();
            System.out.println(s);
        }

    }
}

3. 出力

出力の使用法は入力の使用法と非常に似ており、キー操作は書き込みです。 

書き込む前にファイルを開き、書き込み後にファイルを閉じる必要があります。

出力ストリーム オブジェクト (バイト ストリームか文字ストリームかに関係なく) は、ファイルを開いた後にファイルの内容をクリアします。

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Scanner;

public class Demo8 {
    public static void main(String[] args) throws IOException {
        try(InputStream inputStream = new FileInputStream("d:/test.txt")){
            Scanner scanner = new Scanner(inputStream);
            //此时就是从 test.txt 这个文件中读取数据了
            String s = scanner.next();
            System.out.println(s);
        }

    }
}

追記で開くこともできますが、この時点では内容は消去されません。 

ここでは紹介しませんが、読み書きともにランダムアクセスにも対応しており、カーソルを指定位置に移動して読み書きすることも可能です。

OutputStream の使用方法はまったく同じです。

ただし、write メソッドは文字列パラメーターをサポートできず、バイトまたはバイト配列でのみ書き込むことができます。


例: 指定されたディレクトリをスキャンし、名前に指定された文字が含まれる通常のファイル (ディレクトリを除く) をすべて検索し、このファイルを削除するかどうかをユーザーに尋ねます。

import java.io.File;
import java.util.Scanner;

public class Demo10 {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        //1、用户输入一个目录,后续的查找都是针对这个目录进行的
        System.out.println("请输入要搜索的目录");
        File rootPath = new File(scanner.next());

        //2、再让用户输入要搜索和删除的关键粗
        System.out.println("请输入要删除的关键字");
        String word = scanner.next();

        //3、判断当前目录是否有效
        if (!rootPath.isDirectory()){
            System.out.println("此时输入的路径不是合法目录");
            return;
        }

        //4、遍历目录,从根目录出发,按照深度优先(递归) 的方式进行
        scanDir(rootPath,word);
    }
    public static void scanDir(File currentDir,String word){
        //1、先列出当前目录中包含哪些内容
        File[] files = currentDir.listFiles();
        if (files == null || files.length == 0){
            //空的目录或者非法的目录
            return;
        }
        //2、遍历列出的文件,分两个情况进行讨论
        for(File f : files){
            if (f.isFile()){
                //如果当前文件是普通文件,看看文件名是否包含了 word ,来决定是否要删除
                dealFile(f,word);
            }else {
                //如果当前文件是目录文件,就递归执行 scanDir
                scanDir(f,word);
            }
        }
    }
    public static void dealFile(File f,String word){
        Scanner scanner = new Scanner(System.in);
        //1、先判断当前文件是否包含 word
        if (!f.getName().contains(word)){
            //此时文件不包含 word,
            return;
        }
        //2、包含 word,询问用户是否删除该文件
        System.out.println("该文件是: " + f.getAbsolutePath() + ",是否确认删除(Y / N )");
        String choice = scanner.next();
        if (choice.equals("Y") || choice.equals("y")){
            f.delete();
        }
    }
}

例: 通常のファイルコピーの実行

import java.io.*;
import java.util.Scanner;

public class Demo11 {
    public static void main(String[] args) throws IOException {
        System.out.println("请输入要复制的文件路径");
        Scanner scanner = new Scanner(System.in);
        String src = scanner.next();
        File srcfile= new File(src);
        if (!srcfile.isFile()){
            System.out.println("您输入的源文件路径是非法的");
            return;
        }
        System.out.println("请输入要复制到的目标路径");
        String dest = scanner.next();
        File destfile= new File(dest);
        //不要求目标文件存在,但是得保证目标文件所在的目录是存在的
        if (!destfile.getParentFile().isDirectory()){
            System.out.println("您输入的目标文件路径是非法的");
            return;
        }

        //2、进行复制操作的过程,按照字节流打开
        try(InputStream inputStream = new FileInputStream(srcfile);
            OutputStream outputStream = new FileOutputStream(destfile)){
                while(true){
                    byte[] buffer = new byte[1024];
                    int n = inputStream.read(buffer);
                    if (n == -1){
                        System.out.println("读取到 eof,循环结束");
                        break;
                    }
                    outputStream.write(buffer,0,n);
                }
            }
    }
}

おすすめ

転載: blog.csdn.net/weixin_73616913/article/details/132257024