Maison >interface Web >js tutoriel >Explication détaillée du fichier Node.js operations_node.js
Node dispose d'un ensemble d'API de flux de données qui peuvent traiter des fichiers comme les flux réseau. Il est très pratique à utiliser, mais il permet uniquement le traitement séquentiel des fichiers et ne peut pas lire et écrire des fichiers de manière aléatoire. Par conséquent, certaines opérations du système de fichiers de niveau inférieur doivent être utilisées.
Ce chapitre couvre les bases du traitement des fichiers, notamment comment ouvrir un fichier, lire une partie du fichier, écrire des données et fermer le fichier.
De nombreuses API de fichiers de Node sont presque des répliques des API de fichiers correspondantes sous UNIX (POSIX). Par exemple, la façon d'utiliser les descripteurs de fichiers est la même que sous UNIX. Le descripteur de fichier dans Node est également un nombre entier, représentant un. entité. Index dans la table des descripteurs de fichiers de processus.
Il existe 3 descripteurs de fichiers spéciaux : 1, 2 et 3. Ils représentent respectivement les descripteurs de fichiers d’entrée standard, de sortie standard et d’erreur standard. L'entrée standard, comme son nom l'indique, est un flux en lecture seule que les processus utilisent pour lire les données de la console ou du canal de processus. La sortie standard et l'erreur standard sont des descripteurs de fichiers utilisés uniquement pour générer des données. Ils sont souvent utilisés pour afficher des données vers la console, d'autres processus ou des fichiers. L'erreur standard est responsable de la sortie des informations d'erreur et la sortie standard est responsable de la sortie du processus ordinaire.
Une fois le processus lancé, ces descripteurs de fichiers peuvent être utilisés. Ils n'ont pas réellement de fichiers physiques correspondants. Vous ne pouvez pas lire et écrire des données à une position aléatoire (Note du traducteur : le texte original est Vous pouvez écrire et lire à partir de positions spécifiques dans le fichier. Selon le contexte, l'auteur peut avoir manqué un "non"), vous ne pouvez exploiter le réseau que comme si les données étaient lues et sorties séquentiellement comme un flux de données, et les données écrites ne peuvent pas être modifiées.
Les fichiers ordinaires ne sont pas soumis à cette restriction. Par exemple, dans Node, vous pouvez créer des fichiers qui ne peuvent ajouter des données qu'à la queue, et vous pouvez également créer des fichiers qui lisent et écrivent des emplacements aléatoires.
Presque toutes les opérations liées aux fichiers impliquent le traitement des chemins de fichiers. Ce chapitre présentera d'abord ces fonctions d'outils, puis expliquera en profondeur les opérations de lecture, d'écriture et de données sur les fichiers
Traitement des chemins de fichiers
Les chemins de fichiers sont divisés en chemins relatifs et chemins absolus, qui sont utilisés pour représenter des fichiers spécifiques. Vous pouvez fusionner les chemins de fichiers, extraire les informations sur le nom de fichier et même détecter si un fichier existe.
Dans Node, vous pouvez utiliser des chaînes pour traiter les chemins de fichiers, mais cela compliquera le problème. Par exemple, si vous souhaitez connecter différentes parties du chemin, certaines parties se terminent par "/" et d'autres non, et le. les séparateurs de chemin sont différents. Le système d'exploitation peut également être différent, donc lorsque vous les connectez, le code sera très verbeux et fastidieux.
Heureusement, Node dispose d'un module appelé path, qui peut vous aider à standardiser, vous connecter, analyser les chemins, convertir des chemins absolus en chemins relatifs, extraire diverses parties d'informations du chemin et détecter si le fichier existe. En général, le module path n'est en fait qu'un traitement de chaîne, et il ne va pas au système de fichiers pour vérification (sauf pour la fonction path.exists).
Standardisation des chemins
C'est généralement une bonne idée de normaliser les chemins avant de les stocker ou de les utiliser. Par exemple, les chemins de fichiers obtenus par les entrées utilisateur ou les fichiers de configuration, ou les chemins connectés par deux chemins ou plus, doivent généralement être standardisés. Vous pouvez utiliser la fonction normalize du module path pour normaliser un chemin, et il peut également gérer "..", "." et "//". Par exemple :
path.normalize('/foo/bar//baz/asdf/quux/..');
// => '/foo/bar/baz/asdf'
Chemin de connexion
En utilisant la fonction path.join(), vous pouvez connecter n'importe quel nombre de chaînes de chemin. Il suffit de transmettre toutes les chaînes de chemin à la fonction join() dans l'ordre :
path.join('/foo', 'bar', 'baz/asdf', 'quux', '..');
// => '/foo/bar/baz/asdf'
Comme vous pouvez le voir, path.join() normalisera automatiquement le chemin en interne.
Analyser le chemin
Utilisez path.resolve() pour résoudre plusieurs chemins en un chemin absolu. Sa fonction revient à effectuer une opération "cd" sur ces chemins un par un Contrairement aux paramètres de la commande cd, ces chemins peuvent être des fichiers, et ils ne doivent pas nécessairement exister - la méthode path.resolve() n'y accède pas. le système de fichiers sous-jacent. Déterminez si le chemin existe, c'est juste une manipulation de chaîne.
Par exemple :
path.resolve('/foo/bar', './baz');
// =>
path.resolve('/foo/bar', '/tmp/file/');// =>
path.relative() peut vous indiquer comment passer d'une adresse absolue à une autre, par exemple :
// =>
Prenez le chemin "/foo/bar/myfile.txt" comme exemple Si vous souhaitez récupérer tout le contenu du répertoire parent (/foo/bar), ou lire d'autres fichiers dans le même répertoire, pour cela. , vous devez utiliser path.dirname(filePath) pour obtenir la partie répertoire du chemin du fichier, tel que :
Ou, si vous souhaitez obtenir le nom du fichier à partir du chemin du fichier, qui est la dernière partie du chemin du fichier, vous pouvez utiliser la fonction path.basename :
Copier le code
Le chemin du fichier peut également contenir l'extension du fichier, qui est généralement la partie de la chaîne après le dernier caractère "."
path.basename peut également accepter une chaîne d'extension comme deuxième paramètre, de sorte que le nom de fichier renvoyé supprimera automatiquement l'extension et ne renverra que la partie nom du fichier :
path.basename('/foo/bar/baz/asdf/quux.html', '.html');
// => '.html'
path.extname('/a/b.c/index');
// =>
path.extname('/a/b.c/.');
// =>
path.extname('/a/b.c/d.');// =>
Vérifiez si le chemin existe
Jusqu'à présent, les opérations de traitement de chemin mentionnées ci-dessus n'ont rien à voir avec le système de fichiers sous-jacent, ce ne sont que quelques opérations de chaîne. Cependant, vous devez parfois déterminer si un chemin de fichier existe. Par exemple, vous devez parfois déterminer si un fichier ou un répertoire existe, puis le créer s'il n'existe pas. Vous pouvez utiliser path.exsits() : .
Copier le code
// = & gt; vrai
});
path.exists('/does_not_exist', function(exists) {
console.log('existe :', existe);
// = & gt; faux
});
Remarque : à partir de la version Node 0.8, exist a été déplacé du module path vers le module fs et remplacé par fs.exists À l'exception de l'espace de noms, rien d'autre n'a changé :
fs.exists('/does_not_exist', function(exists) {
console.log('existe :', existe);
});
// =>
Le module fs contient toutes les fonctions liées à la requête et au traitement des fichiers. Avec ces fonctions, vous pouvez interroger des informations sur les fichiers, lire, écrire et fermer des fichiers. Importez le module fs comme ceci :
Parfois, vous aurez peut-être besoin de connaître la taille du fichier, la date de création ou les autorisations et d'autres informations sur le fichier. Vous pouvez utiliser la fonction fs.stath pour interroger les méta-informations du fichier ou du répertoire :
.if (err) { throw err;}
console.log(stats);
});
mode : 33188,
nlien : 1,
uid : 0,
gid : 0,
rdev : 0,
taille : 5086,
noirtaille : 4096,
blocs : 0,
heure : vendredi 18 novembre 2011 22:44:47 GMT,
heure : jeu. 8 septembre 2011 23:50:04 GMT,
heure : jeu. 8 septembre 2011 23:50:04 GMT }
1. L'appel fs.stat() transmettra une instance de la classe stats en tant que paramètre à sa fonction de rappel. Vous pouvez utiliser l'instance stats comme suit :
2.stats.isFile() - Renvoie vrai s'il s'agit d'un fichier standard, pas d'un répertoire, d'un socket, d'un lien symbolique ou d'un périphérique, sinon faux
3.stats.isDiretory() - Renvoie vrai s'il s'agit d'un répertoire, sinon faux
4.stats.isBlockDevice() - Renvoie vrai s'il s'agit d'un périphérique bloc Dans la plupart des systèmes UNIX, les périphériques bloc sont généralement situés dans le répertoire /dev
.
5.stats.isChracterDevice() - Renvoie vrai s'il s'agit d'un périphérique de caractère
6.stats.isSymbolickLink() - Renvoie vrai s'il s'agit d'un lien de fichier
7.stats.isFifo() - Renvoie vrai s'il s'agit d'un FIFO (un type spécial de tube nommé UNIX)
8.stats.isSocket() - s'il s'agit d'un socket UNIX (À FAIRE : googler)
Ouvrir le fichier
Avant de lire ou de traiter un fichier, vous devez d'abord utiliser la fonction fs.open pour ouvrir le fichier. Ensuite, la fonction de rappel que vous fournissez sera appelée et obtiendra le descripteur de fichier. Vous pourrez utiliser ce descripteur de fichier pour lire plus tard. à ce fichier déjà ouvert :
fs.open('/path/to/file', 'r', function(err, fd) {
// obtenu le descripteur de fichier fd
});
Le premier paramètre de fs.open est le chemin du fichier, et le deuxième paramètre correspond à certaines balises utilisées pour indiquer le mode dans lequel ouvrir le fichier. Ces balises peuvent être r, r, w, w, a ou a. Vous trouverez ci-dessous une description de ces balises (extraite de la page fopen de la documentation UNIX)
1.r - Ouvrir le fichier en mode lecture seule, la position initiale du flux de données est au début du fichier
2.r - Ouvrez le fichier en mode lecture-écriture, la position initiale du flux de données est au début du fichier
3.w - Si le fichier existe, la longueur du fichier sera remise à 0, c'est-à-dire que le contenu du fichier sera perdu. S'il n'existe pas, essayez de le créer. La position initiale du flux de données est au début du fichier
4.w - Ouvrez le fichier en mode lecture-écriture. Si le fichier n'existe pas, essayez de le créer. Si le fichier existe, définissez la longueur du fichier sur 0, c'est-à-dire que le contenu du fichier sera perdu. La position initiale du flux de données est au début du fichier
5.a - Ouvrez le fichier en mode écriture seule. Si le fichier n'existe pas, essayez de le créer. La position initiale du flux de données est à la fin du fichier. Chaque opération d'écriture ultérieure ajoutera les données au fichier. fin du fichier.
6.a - Ouvrez le fichier en lecture et en écriture. Si le fichier n'existe pas, essayez de le créer. La position initiale du flux de données est à la fin du fichier. Chaque opération d'écriture ultérieure ajoutera les données à la fin. du dossier.
Lire le fichier
Une fois le fichier ouvert, vous pouvez commencer à lire le contenu du fichier, mais avant de commencer, vous devez d'abord créer un tampon pour placer les données. Cet objet tampon sera transmis à la fonction fs.read en tant que paramètre et rempli de données par fs.read.
fs.open('./my_file.txt', 'r', fonction ouverte (err, fd) {
if (err) { throw err }
var readBuffer = new Buffer(1024),
bufferOffset = 0,
bufferLength = readBuffer.length,
filePosition = 100;
fs.read(fd,
readBuffer,
bufferOffset,
bufferLength,
filePosition,
fonction read(err, readBytes) {
if (err) { throw err; >
console.log('just read ' readBytes ' bytes');
if (readBytes > 0) {
console.log(readBuffer.slice(0, readBytes));
}
});
});
上面代码尝试打开一个文件,当成功打开后(调用opened函数),开始请求从文件流第100个字节开始读取随后1024个字节的数据(第11行)。
fs.read()当下面三种情况发生时,它会被调用:
1.有错误发生
2.成功读取了数据
3.没有数据可读
如果有错误发生,第一个参数(err)会为回调函数提供一个包含错误信息的对象,否则这个Il s'agit d'un null.读到缓冲区里数据的大小,如果值是0,则表示到达了文件末尾。
注意:一旦把缓冲区对象传递给fs.open(),缓冲对象的控制权就转移给给了read命令,只有当回调函数被调用,缓冲区对象的控制权才会回到你手里.完整的数据,更糟的情况是,你可能会并发地往这个缓冲区对象里写数据。
写文件
if (err) { throw err; >
var writeBuffer = new Buffer('écrire cette chaîne'),
bufferPosition = 0,
bufferLength = writeBuffer.length, filePosition = null;
fs.write( fd,
writeBuffer,
bufferPosition,
bufferLength,
filePosition,
la fonction a écrit (euh, écrit) {
if (err) { throw err; >
console.log('write ' writing ' bytes');
});
});
Dans cet exemple, la 2ème ligne de code (Note du traducteur : le texte original est 3) tente d'ouvrir un fichier en mode ajout (a), puis la 7ème ligne de code (Note du traducteur : le texte original est 9) écrit données dans le fichier. L'objet buffer doit être accompagné de plusieurs informations en paramètres :
1. Données tampon
2. D'où partent les données à écrire dans le tampon
3. La longueur des données à écrire
4.À quel emplacement du fichier les données sont-elles écrites ?
5. La fonction de rappel write
Dans cet exemple, le paramètre filePostion est nul, ce qui signifie que la fonction d'écriture écrira les données à l'emplacement actuel du pointeur de fichier. Étant donné que le fichier est ouvert en mode ajout, le pointeur de fichier est à la fin du fichier. déposer.
Semblable à l'opération de lecture, n'utilisez jamais l'objet tampon entrant pendant l'exécution de fs.write. Une fois que fs.write commence à s'exécuter, il prend le contrôle de cet objet tampon. Vous ne pouvez qu'attendre que la fonction de rappel soit appelée avant de pouvoir l'utiliser à nouveau.
Fermer le dossier
Vous avez peut-être remarqué qu'aucun des exemples de ce chapitre ne contient jusqu'à présent de code pour fermer le fichier. Comme il s'agit d'exemples petits et simples qui ne sont utilisés qu'une seule fois, le système d'exploitation s'assure que tous les fichiers sont fermés à la fin du processus Node.
Cependant, dans une application réelle, une fois que vous ouvrez un fichier, vous voulez être sûr de le fermer éventuellement. Pour ce faire, vous devez garder une trace de tous ces descripteurs de fichiers ouverts, puis éventuellement les fermer en appelant fs.close(fd[,callback]) lorsqu'ils ne sont plus utilisés. Il est facile de manquer un descripteur de fichier si vous ne faites pas attention. L'exemple suivant fournit une fonction appelée openAndWriteToSystemLog, montrant comment fermer le fichier avec précaution :
Ici, une fonction appelée openAndWriteToSystemLog est fournie, qui accepte un objet tampon contenant les données à écrire, et une fonction de rappel qui est appelée une fois l'opération terminée ou si une erreur se produit, la première fonction de rappel. Les paramètres contiendront l’objet d’erreur.
Faites attention à la fonction interne notifyError, qui fermera le fichier et signalera l'erreur survenue.
Remarque : à ce stade, vous savez comment utiliser des opérations atomiques de bas niveau pour ouvrir, lire, écrire et fermer des fichiers. Cependant, Node dispose également d'un ensemble de constructeurs plus avancés qui vous permettent de travailler avec des fichiers de manière plus simple.
Par exemple, si vous souhaitez utiliser un moyen sûr pour autoriser deux opérations d'écriture ou plus à ajouter simultanément des données à un fichier, vous pouvez utiliser WriteStream.
De plus, si vous souhaitez lire une certaine zone d'un fichier, pensez à utiliser ReadStream. Ces deux cas d'utilisation seront présentés au chapitre 9 « Flux de lecture et d'écriture de données ».
Résumé
Lorsque vous utilisez des fichiers, vous devez traiter et extraire les informations de chemin de fichier dans la plupart des cas. En utilisant le module de chemin, vous pouvez concaténer des chemins, standardiser des chemins, calculer des différences de chemin et convertir des chemins relatifs en chemins absolus. Vous pouvez extraire l'extension, le nom de fichier, le répertoire et d'autres composants du chemin de fichier spécifié.
Node fournit un ensemble d'API de bas niveau dans le module fs pour accéder au système de fichiers. Les API de bas niveau utilisent des descripteurs de fichiers pour faire fonctionner les fichiers. Vous pouvez ouvrir un fichier avec fs.open, écrire dans un fichier avec fs.write, lire un fichier avec fs.read et fermer un fichier avec fs.close.
Vous devez toujours utiliser une logique de gestion des erreurs appropriée pour fermer les fichiers lorsqu'une erreur se produit - en vous assurant que les descripteurs de fichiers ouverts sont fermés avant le retour de l'appel.