Flux Java IO - introduction détaillée à l'utilisation du flux d'octets

Introduction de base au flux IO

Vue d'ensemble des flux IO :

I représente l'entrée, qui est le processus de lecture des données du fichier du disque dur dans la mémoire, qui est appelée entrée et est responsable de la lecture.

O signifie sortie, qui est le processus des données du programme de mémoire de la mémoire à l'écriture sur le fichier du disque dur, appelé sortie, responsable de l'écriture.

insérez la description de l'image ici

Classification des flux IO :

Classé par sens :

  • flux d'entrée
  • flux de sortie

Selon la plus petite unité de données du flux, il est divisé en :

  • Flux d'octets : peut exploiter tous les types de fichiers ( y compris l'audio, la vidéo, les images d'écran, etc. )
  • Flux de caractères : ne peut fonctionner que sur des fichiers en texte brut ( y compris les fichiers java, les fichiers txt, etc. )

Pour résumer les quatre grandes catégories de flux :

Flux d'entrée d'octets : basé sur la mémoire, le flux dans lequel les données des fichiers/réseaux du disque sont lus dans la mémoire sous forme d'octets est appelé flux d'entrée d'octets.

Flux de sortie d'octets : basé sur la mémoire, le flux qui écrit les données de la mémoire dans un fichier disque ou un réseau en octets est appelé flux de sortie d'octets.

Flux d'entrée de caractères : basé sur la mémoire, le flux dans lequel les données des fichiers/réseaux du disque sont lus dans la mémoire sous forme de caractères est appelé flux d'entrée de caractères.

Flux de sortie de caractères : basé sur la mémoire, le flux qui écrit les données de la mémoire dans un fichier disque ou un support réseau en caractères est appelé flux de sortie de caractères.

insérez la description de l'image ici

Utilisation de flux d'octets

insérez la description de l'image ici

flux d'entrée d'octets de fichier

Créer un flux d'entrée d'octets

Flux d'entrée d'octets de fichier : implémentez la classe FileInputStream

Fonction : sur la base de la mémoire, lit les données du fichier disque dans la mémoire en octets.

Le constructeur est le suivant :

constructeur illustrer
public FileInputStream (fichier fichier) Créer un canal de flux d'entrée d'octets pour se connecter à l'objet de fichier source
public FileInputStream(String pathname) Créer un canal de flux d'entrée d'octets connecté au chemin du fichier source

Exemple de code :

public static void main(String[] args) throws FileNotFoundException {
    
    
  	// 写法一: 创建字节输入流与源文件对象接通
    InputStream inp = new FileInputStream(new File("/file-io-app/src/test.txt"));
}
public static void main(String[] args) throws FileNotFoundException {
    
    
  	// 写法二: 创建字节输入流管道与源文件路径接通
    InputStream inp = new FileInputStream("/file-io-app/src/test.txt");
}

lire un octet à la fois

nom de la méthode illustrer
lire() Renvoie un octet à la fois, ou -1 s'il n'y a plus d'octets à lire

Par exemple, le contenu du fichier Bloc-notes que nous lisons est : abcd123

public static void main(String[] args) throws Exception {
    
    
    InputStream inp = new FileInputStream("/Users/chenyq/Documents/learn_Java/code/file-io-app/src/test.txt");

    int a = inp.read();
    System.out.println(a); // 97
    System.out.println((char) a); // a

    // 一次输入一个字节
    System.out.println(inp.read()); // 98
    System.out.println(inp.read()); // 99
    System.out.println(inp.read()); // 100
    System.out.println(inp.read()); // 49
    System.out.println(inp.read()); // 50
    System.out.println(inp.read()); // 51
    // 无字节可读返回-1
    System.out.println(inp.read()); // -1
}

Nous pouvons parcourir les octets du fichier

public static void main(String[] args) throws Exception {
    
    
    InputStream inp = new FileInputStream("/Users/chenyq/Documents/learn_Java/code/file-io-app/src/test.txt");

    int b;
    while ((b = inp.read()) != -1) {
    
    
        System.out.print((char) b); // abcd123
    }
}

La lecture d'un octet à la fois pose les problèmes suivants

performances lentes

Le problème des caractères tronqués ne peut pas être évité lors de la lecture des caractères chinois.


lire un tableau à la fois

nom de la méthode illustrer
lire (octet [] tampon) Chaque fois qu'un tableau d'octets est lu, le nombre d'octets lus est renvoyé et -1 est renvoyé s'il n'y a plus d'octets lisibles.

Définir un tableau d'octets pour recevoir le nombre d'octets lus

Par exemple, dans le code suivant, le contenu du fichier est : abcd123, trois octets sont lus à chaque fois, et chaque lecture écrasera le contenu du tableau précédent, mais la troisième lecture ne lit qu'un seul caractère, donc uniquement Écrase le premier élément du tableau de caractères lu la dernière fois, le résultat est : 312

public static void main(String[] args) throws Exception {
    
    
    InputStream inp = new FileInputStream("/Users/chenyq/Documents/learn_Java/code/file-io-app/src/test.txt");

    // 定义一个长度为3的字节数组
    byte[] arr = new byte[3];

    // 第一次读取一个字节数组
    int len1 = inp.read(arr);
    System.out.println("读取字节数: " + len1); // 读取字节数: 3
    // 对字节数组进行解码
    String res1 = new String(arr);
    System.out.println(res1); // abc

    // 第二次读取一个字节数组
    int len2 = inp.read(arr);
    System.out.println("读取字节数: " + len2); // 读取字节数: 3
    // 对字节数组进行解码
    String res2 = new String(arr);
    System.out.println(res2); // d12

    // 第三次读取一个字节数组
    int len3 = inp.read(arr);
    System.out.println("读取字节数: " + len3); // 读取字节数: 1
    // 对字节数组进行解码
    String res3 = new String(arr);
    System.out.println(res3); // 312

    // 无字节可读返回-1
    System.out.println(inp.read()); // -1
}

Le deuxième paramètre de String peut spécifier la position de début et le troisième paramètre peut spécifier la position de fin. Ces deux paramètres peuvent être utilisés pour résoudre les inconvénients de la troisième lecture

Et la boucle améliore le code optimisé

public static void main(String[] args) throws Exception {
    
    
    InputStream inp = new FileInputStream("/Users/chenyq/Documents/learn_Java/code/file-io-app/src/test.txt");

    byte[] arr = new byte[3];
    int len;
    while ((len = inp.read(arr)) != -1) {
    
    
        String res = new String(arr, 0, len);
        System.out.print(res); // abcd123
    }
}

Les inconvénients de lire un tableau à la fois :

Les performances de lecture ont été améliorées

Le problème des caractères tronqués ne peut pas être évité lors de la lecture des caractères chinois.


Lire tous les octets à la fois

Pour résoudre le problème des caractères chinois brouillés, nous pouvons définir un tableau d'octets aussi grand que le fichier et lire tous les octets du fichier en une seule fois.

Inconvénient : si le fichier est trop volumineux, le tableau d'octets peut provoquer un débordement de mémoire.

Par exemple, lisez un fichier comme celui présenté ci-dessous

insérez la description de l'image ici

Méthode 1 :

Définissez vous-même un tableau d'octets aussi grand que la taille du fichier, puis utilisez la méthode de lecture du tableau d'octets pour terminer la lecture unique.

public static void main(String[] args) throws Exception {
    
    
    File file = new File("/Users/chenyq/Documents/learn_Java/code/file-io-app/src/test.txt");
    InputStream inp = new FileInputStream(file);

    // 创建一个与文件大小一样的字节数组
    byte[] arr = new byte[(int) file.length()];

    // 读取文件, 获取读取的字节长度
    int len = inp.read(arr);
    System.out.println(len); // 252

    // 对字节数组进行解码
    String res = new String(arr);
    System.out.println(res);
    // abcd123我爱Java学习Java.abcd123我爱Java学习Java.abcd123我爱Java学习Java.
    // abcd123我爱Java学习Java.abcd123我爱Java学习Java.abcd123我爱Java学习Java.
    // abcd123我爱Java学习Java.abcd123我爱Java学习Java.abcd123我爱Java学习Java.
}

Méthode 2 :

L'officiel fournit l'API suivante pour le flux d'entrée d'octets InputStream, qui peut directement lire toutes les données du fichier dans un tableau d'octets

nom de la méthode illustrer
readAllBytes() Lire directement toutes les données d'octets de l'objet fichier correspondant au flux d'entrée d'octets actuel, puis les charger dans un tableau d'octets et revenir
public static void main(String[] args) throws Exception {
    
    
    InputStream inp = new FileInputStream("/Users/chenyq/Documents/learn_Java/code/file-io-app/src/test.txt");

    // 获取文件的全部字节, 并返回一个字节数组
    byte[] arr = inp.readAllBytes();
    // 对字节数组进行解码
    String res = new String(arr);
    System.out.println(res);
    // abcd123我爱Java学习Java.abcd123我爱Java学习Java.abcd123我爱Java学习Java.
    // abcd123我爱Java学习Java.abcd123我爱Java学习Java.abcd123我爱Java学习Java.
    // abcd123我爱Java学习Java.abcd123我爱Java学习Java.abcd123我爱Java学习Java.
}

flux de sortie d'octets de fichier

Créer un flux de sortie d'octets

Flux de sortie d'octets de fichier : implémentez la classe FileOutputStream

Fonction : sur la base de la mémoire, les données de la mémoire sont écrites sur le fichier disque sous forme d'octets.

Le constructeur est le suivant :

constructeur illustrer
FileOutputStream(Fichier fichier) Créer un canal de flux de sortie d'octets connecté à l'objet de fichier source
FileOutputStream (chemin du fichier de chaîne) Créer un canal de flux de sortie d'octets connecté au chemin du fichier source
public static void main(String[] args) throws Exception {
    
    
    // 写法一: 创建输出流与源文件对象接通
    OutputStream oup = new FileOutputStream(new File("/Users/chenyq/Documents/learn_Java/code/file-io-app/src/test.txt"));
}
public static void main(String[] args) throws Exception {
    
    
    // 写法二: 创建输出与源文件路径接通(常用)
    OutputStream oup = new FileOutputStream("/Users/chenyq/Documents/learn_Java/code/file-io-app/src/test.txt");

}

écrire dans le flux de sortie du fichier

API pour écrire des données à partir du flux de sortie d'octets du fichier :

nom de la méthode illustrer
écrire (int a) écrire un octet
écrire (octet [] tampon) écrire un tableau d'octets
écriture(byte[] buffer , int pos , int len) Écrire une partie d'un tableau d'octets.

Actualisation du flux et fermeture de l'API :

méthode illustrer
affleurer() Actualiser le flux et continuer à écrire des données
Fermer() Fermez le flux, en libérant des ressources, mais en vidant le flux avant de fermer . Une fois fermées, les données ne peuvent plus être écrites

Remarque : Les données doivent être actualisées lors de l'écriture des données et le flux doit être fermé après son utilisation.

écrire un octet

public static void main(String[] args) throws Exception {
    
    
    OutputStream oup = new FileOutputStream("/Users/chenyq/Documents/learn_Java/code/file-io-app/src/test.txt");

    oup.write('a');
    // 支持写入编码
    oup.write(97);
    // 汉字占三个字节, 所以该方法不可以写入汉字
    // oup.write('我');

    // 写数据必须刷新数据
    oup.flush();
    // 刷新流后可以继续写入数据
    oup.write('b');
    // 使用完后需要关闭流, 关闭后不能再写入数据
    oup.close();
}

écrire un tableau d'octets

public static void main(String[] args) throws Exception {
    
    
    OutputStream oup = new FileOutputStream("/Users/chenyq/Documents/learn_Java/code/file-io-app/src/test.txt");

    // 定义一个字节数组
    byte[] arr = {
    
    'a', 98, 'b', 'c'};
    // 写入中文, 需要将中文编码成字节数组
    byte[] chinese = "中国".getBytes();

    // 写入英文字节数组
    oup.write(arr);
    // 写入中文字节数组
    oup.write(chinese);

    // 关闭流(关闭之前会刷新)
    oup.close();
}

écrire une partie d'un tableau d'octets

public static void main(String[] args) throws Exception {
    
    
    OutputStream oup = new FileOutputStream("/Users/chenyq/Documents/learn_Java/code/file-io-app/src/test.txt");

    // 定义一个字节数组
    byte[] arr = {
    
    'a', 98, 'b', 'c'};
    // 写入数组的第二个和第三个元素
    oup.write(arr, 1, 2);

    // 关闭流(关闭之前会刷新)
    oup.close();
}

Connaissances supplémentaires :

Supplément 1 : lors de l'écriture de contenu, si vous devez modifier la ligne, vous pouvez la convertir \r\n( la fenêtre prend en charge l'entrée \n mais certains systèmes ne la prennent pas en charge, utilisez \r\n pour plus de polyvalence ) en un tableau d'octets et écrivez-le pour obtenir l'effet du saut de ligne

public static void main(String[] args) throws Exception {
    
    
    OutputStream oup = new FileOutputStream("/Users/chenyq/Documents/learn_Java/code/file-io-app/src/test.txt");

    // 定义一个字节数组
    byte[] arr = {
    
    'a', 98, 'b', 'c'};
    oup.write(arr);
    // 写入换行
    oup.write("\r\n".getBytes());
    // 写入数组的第二个和第三个元素
    oup.write(arr, 1, 2);

    // 关闭流(关闭之前会刷新)
    oup.close();
}

Supplément 2 : lors de l'écriture d'un fichier, le fichier d'origine sera d'abord effacé, puis de nouvelles données seront écrites. Si nous voulons ajouter de nouvelles données basées sur les données du fichier d'origine, nous devons définir le deuxième paramètre du jeu de constructeurs vrai

constructeur illustrer
FileOutputStream (fichier, ajout booléen) Créez un pipeline de flux de sortie d'octets connecté à l'objet de fichier source et les données peuvent être ajoutées
FileOutputStream(String filepath,boolean append) Créez un pipeline de flux de sortie d'octets connecté au chemin du fichier source et les données peuvent être ajoutées
public static void main(String[] args) throws Exception {
    
    
	  // 设置为true即可
    OutputStream oup = new FileOutputStream("/Users/chenyq/Documents/learn_Java/code/file-io-app/src/test.txt", true);
}

exercice de copie de fichier

Exigences :

Copiez le fichier test.pdf dans le fichier newtest.pdf dans un autre répertoire

Analyse d'idée :

Créer un objet de flux d'entrée d'octets à partir d'une source de données

Créer un objet de flux de sortie d'octets basé sur la destination

Lire et écrire des données, copier une vidéo

libérer des ressources

Exemple de code :

public static void main(String[] args) {
    
    
    try {
    
    
        // 创建要复制文件的字节输入流
        InputStream inp = new FileInputStream("/Users/chenyq/Documents/learn_Java/code/file-io-app/src/test.pdf");
        // 创建目标路径的字节输出流
        OutputStream oup = new FileOutputStream("/Users/chenyq/Documents/newtest.pdf");

        // 使用文件输入流获取要复制文件的全部数据的字节数组
        byte[] arr = inp.readAllBytes();
        // 使用文件输出流将字节数组写入目标文件
        oup.write(arr);
        System.out.println("复制成功!");

        // 释放资源
        inp.close();
        oup.close();
    } catch (IOException e) {
    
    
        e.printStackTrace();
    }
}

Question : Quels types de fichiers les flux d'octets peuvent-ils copier ?

La couche inférieure de tout fichier est constituée d'octets et la copie est un transfert mot à mot d'octets. Tant que le format et l'encodage des fichiers précédents et suivants sont cohérents, il n'y a pas de problème.
Résumé : le flux d'octets convient à la copie de fichiers, mais ne convient pas à la sortie en chinois

Je suppose que tu aimes

Origine blog.csdn.net/m0_71485750/article/details/127592978
conseillé
Classement