Analyse principale
Pendant le développement, la fonction de la «transmission continue de point d'arrêt» est très pratique et courante, et elle semble également plus «standard». Nous sommes donc généralement intéressés à étudier comment cette fonction est implémentée?
En Java, vous pouvez également trouver beaucoup d'informations sur la mise en œuvre de fonctions similaires sur Internet. Cependant, la plupart d'entre eux donnent une démo et publient le code source. Il existe très peu d'explications détaillées de son principe de mise en œuvre.
Ainsi, lorsque nous sommes entrés en contact avec pour la première fois, nous pourrions simplement utiliser directement les codes CRTL + C / V, puis le bricoler, mais nous pouvons enfin sortir l'effet. Mais faire cela lorsque vous êtes débutants est évidemment bon et mauvais.
L'avantage est qu'il existe de nombreux codes source et peu d'explications; Si nous sommes prêts à travailler dur, nous rechercherons des informations et étudierons les choses que nous ne comprenons pas dans le code publié par d'autres. En fin de compte, vous obtiendrez probablement beaucoup de récompenses.
Les inconvénients sont également évidents: en tant que débutant, face à beaucoup de code source, il semble que beaucoup de choses ne soient pas familières, il est donc facile d'être intimidé. Même si vous avez une compréhension approximative de l'utilisation à la fin, vous ne comprendrez pas nécessairement le principe de mise en œuvre.
Aujourd'hui, commençons par le point de vue le plus élémentaire et voyons si la soi-disant «continuation de point d'arrêt» est vraiment si «haut de gamme».
En fait, lorsque vous entrez en contact avec une nouvelle "chose", vous pouvez la transformer en quelque chose que nous connaissons davantage pour faire référence et comparer et apprendre. Habituellement, ce sera le double du résultat avec la moitié de l'effort.
Si nous sommes simplement exposés au concept de «transmission continue à point d'arrêt», il sera certainement difficile d'expliquer clairement un, deux et trois. Ensuite, nous vous familiariserons avec "jouer à des jeux".
Ok, alors supposons que nous avons maintenant un "jeu RPG de niveau clair". Pensez à ce que nous faisons habituellement en jouant à ce genre de jeu?
Il est évident que le premier jour, nous avons combattu des batailles sanglantes et tué tout le monde, en supposant que nous sommes finalement arrivés au quatrième niveau. Bien que la bataille féroce batte son plein, quand j'ai regardé l'horloge sur le mur, il était déjà à 12 heures du matin et il était temps d'aller me coucher.
C'était très embarrassant à ce moment. Afin de suivre le rythme avec succès de la progression de notre jeu la prochaine fois que nous jouerons, que devons-nous faire?
C'est très simple. Nous ne désactivons pas le jeu, nous allons nous coucher et continuons à jouer le lendemain. C'est OK, mais il semble qu'il y ait quelque chose qui met les gens mal à l'aise.
Donc, pour le moment, si le jeu a une fonction appelée "sauvegarder", ce sera très important. Nous sélectionnons directement l'archive, entrons le nom de l'archive "quatrième niveau", puis nous pouvons fermer le jeu.
Lorsque nous jouerons le jeu la prochaine fois, nous trouverons directement la sauvegarde du "quatrième niveau", puis lirons le fichier, puis nous pourrons continuer à jouer au jeu.
À l'heure actuelle, la soi-disant «transmission continue continue» est facile à comprendre. Suivons notre idée précédente de «jouer à des jeux»:
Supposons qu'il y ait un fichier que nous devons télécharger maintenant. Lorsque nous en téléchargeons une partie, une situation se produit, comme: l'ordinateur se bloque, l'alimentation est sortie, le réseau est interrompu, etc.
En fait, c'est comme lorsque nous jouions à des jeux auparavant, nous avions soudainement besoin d'aller se coucher et de nous reposer à 12 heures. Ok, alors la situation à ce moment est:
• Si le jeu ne peut pas être sauvé, cela signifie que la prochaine fois que nous jouons, les progrès des 4 niveaux qui se sont écoulés cette fois seront perdus et que nous ne pouvons pas suivre le jeu.
• En conséquence, si le comportement "Download" ne peut pas enregistrer une progression de ce téléchargement. Ensuite, lorsque nous téléchargeons à nouveau ce fichier, nous ne pouvons que recommencer.
À ce stade, nous avons en fait découvert que la clé du comportement que nous avons mentionné ci-dessus est le mot « continuer »!
Pour atteindre le but de "continuer" un comportement déconnecté, la clé est d'avoir un "média" capable d'enregistrer et de lire les informations du nœud où le comportement a une "interruption".
Se transformer au monde de la programmation
En fait, il s'agit du principe le plus élémentaire de la "transmission continue du point de rupture". En termes simples, nous devons enregistrer les informations de localisation d'interruption lorsque le comportement de téléchargement est interrompu, puis les lire dans le comportement suivant.
Avec ces informations de localisation, réfléchissez à ce que nous devons faire. Oui, c'est très simple. Lorsqu'un nouveau comportement de téléchargement commence, téléchargez le contenu directement à partir de cet emplacement de l'enregistrement et ne démarre plus à partir de zéro.
Eh bien, nous avons parlé du principe de si longtemps en langage clair et avons commencé à nous ennuyer. Alors, résumons-le à la fin, puis jetons un coup d'œil à la façon dont nous devons convertir les principes dans le monde de la programmation.
• Lorsque le «comportement de téléchargement (téléchargement)» est interrompu, nous devons enregistrer l'emplacement (position) de ce téléchargement (téléchargement).
• Lorsque le comportement "continuer" commence, nous sautons directement au message pour continuer le téléchargement (téléchargement).
De toute évidence, la clé du problème réside dans la soi-disant «position». Dans le "jeu de niveau de passe", nous avons mentionné, "quel niveau" peut être utilisé comme unité de cette position.
Ainsi, lorsque nous passons à la soi-disant «transmission continue à point d'arrêt», que devons-nous utiliser pour mesurer la «position»? De toute évidence, il est de retour au binaire parce que l'essence ici n'est rien de plus que de lire et d'écrire des fichiers.
Ensuite, le reste du travail est très simple. Tout d'abord, enregistrez la position, qui ne semble rien qui vaut la peine de parler, car ce n'est que la persistance des données (mémoire, fichiers, base de données), et nous avons de nombreuses façons.
Une autre clé est que lorsque le comportement "continu" commence, nous devons démarrer les opérations de lecture et d'écriture à partir de la position de position que nous avons enregistrée la dernière fois, nous avons donc besoin de quelque chose de similaire à la fonction "pointeur".
Bien sûr, nous pouvons également trouver un moyen d'implémenter un tel "pointeur", mais heureux que Java nous ait fourni une telle classe, c'est-à-dire RandomAccessFile.
La fonction de cette classe se reflète intuitivement dans son nom et peut accéder aux fichiers au hasard. Jetons un coup d'œil à la description de cette classe dans la documentation de l'API:
Instances de cette classe Prise en charge de la lecture et de l'écriture dans des fichiers accessibles au hasard. L'accès aléatoire aux fichiers se comporte comme un grand tableau d'octets stocké dans le système de fichiers.
Si un fichier est accessible au hasard en mode lecture / écriture, l'opération de sortie est également disponible; L'opération de sortie commence par le pointeur de fichier et fait progresser le pointeur de fichier lorsque l'octet est écrit.
Une opération de sortie après avoir écrit à l'extrémité actuelle d'un tableau implicite fait se développer le tableau. Le pointeur de fichier peut être lu via la méthode GetFilePointer et définir la méthode de recherche.
Après avoir lu les instructions de l'API, nous avons ri. Oui, n'est-ce pas exactement ce que nous voulons? Eh bien, nous aiguisons notre couteau depuis si longtemps, pourquoi ne hachons-nous pas le bois?
Exemple de démonstration
Comme c'est pour la "continuation de point d'arrêt" des fichiers, il est évident que nous créerons d'abord un fichier. Peut-être que les fichiers audio, les fichiers image, etc. seront un peu plus chics.
Mais nous avons déjà dit que aux yeux des grands frères informatiques, ils reviendront finalement à "binaire". Nous allons donc créer un simple fichier "txt" ici, car TXT est plus propice à la compréhension.
Nous créons un fichier nommé "test.txt" dans le répertoire racine du disque D. Le contenu du fichier est très simple, comme le montre la figure:
C'est vrai, ce que nous avons tapé est 6 lettres d'anglais simples. Ensuite, nous cliquez avec le bouton droit → Propriétés:
Nous voyons que le fichier a maintenant une taille de 6 octets. C'est pourquoi nous disons que tout est inséparable de "binaire".
Oui, nous comprenons tous parce que nous sommes entrés dans 6 lettres anglaises, et l'espace de stockage que 1 lettre anglaise occupera est de 1 octet (c'est-à-dire 8 bits).
Jusqu'à présent, ce que nous avons vu est ennuyeux, car c'est fondamentalement un non-sens, et les personnes ayant un peu de connaissances sur ordinateur connaissent ces connaissances. Ne vous inquiétez pas, continuons.
Il est facile de lire et d'écrire un fichier en Java. Supposons que l'exigence actuelle soit "Écrivez ce fichier à partir du lecteur D pour le lecteur E", alors nous allons soulever le clavier et le faire!
Mais n'est-ce pas le soi-disant «téléchargement (téléchargement)» du soi-disant fichier? La seule différence est que le comportement passe de "juste entre les indigènes" à "entre les indigènes" à "entre les autochtones" la lecture et l'écriture des fichiers.
Pour le moment, nous dirons: "Arrêtez de vous exhorter, tout le monde sait ces choses, qu'en est-il de la" transmission continue de point d'arrêt "?" En fait, c'est déjà très simple ici. Nous indiquerons à nouveau que ce que nous devons faire dans la transmission continue de point d'arrêt est:
S'il y a une interruption dans le comportement de lecture et d'écriture précédent, veuillez enregistrer les informations de localisation du contenu du fichier qui ont été lus et écrits cette fois; Lorsque "la continuation démarre", déplacez directement le pointeur ici et commencez à continuer l'opération de lecture et d'écriture.
L'accent répété sur le principe est en fait parce que tant que le principe est compris, le reste est juste des mouvements. C'est comme les "neuf neuf retour à un" Dharma dans les romans d'arts martiaux, le plus haut niveau est de revenir à la source d'origine.
Tant que nous comprenons le principe de toute chose complexe, nous pouvons le dépouiller et le réduire à des choses simples. De même, une série de choses simples, à travers une combinaison logique, forment des choses complexes.
Ensuite, nous retournerons bientôt au chaos et simulerons une "transmission continue de point d'arrêt" sous la forme la plus élémentaire. Ici, nous n'écrivons même pas le code du serveur, et nous le faisons simplement via une classe de test locale.
L'effet que nous voulons réaliser est très simple: écrivez le fichier "test.txt" sur le disque D sur le disque E, mais nous simulerons le comportement "d'interruption" au milieu du processus, puis continuerons à télécharger à nouveau pour finalement terminer l'ensemble du processus.
En d'autres termes, nous considérerons "D lecteur" comme un ordinateur ici, et considérons directement "E le lecteur" comme un serveur. Ensuite, nous n'aurons plus à voir avec le protocole HTTP pour un demi-centime (bien sûr, nous devons encore avoir à voir avec lui dans le développement réel), nous nous soucions donc des principes les plus élémentaires de la «rupture» et de la «poursuite» pour la lecture et l'écriture de fichiers.
Afin d'approfondir notre compréhension par la comparaison, nous écrivons d'abord un morceau de code normal, c'est-à-dire, lisez et écrivez normalement sans interruption:
classe publique test {public static void main (String [] args) {// Source and Target Fichiers Sourcefile = new File ("d: /", "test.txt"); File TargetFile = nouveau fichier ("e: /", "test.txt"); // Stream d'entrée et de sortie FileInputStream fis = null; FileoutputStream fos = null; // Byte de tampon de données [] buf = nouveau octet [1]; try {fis = new FileInputStream (sourcefile); fos = new FileOutputStream (TargetFile); // Lire et écrire des données while (fis.read (buf)! = -1) {System.out.println ("Data Data ..."); Fos.Write (BUF); }} catch (filenotfoundException e) {System.out.println ("Le fichier spécifié n'existe pas"); } catch (ioException e) {// todo: gère l'exception} enfin {try {// ferme le flux d'entrée et de sortie if (fis! = null) fis.close (); if (fos! = null) fos.close (); } catch (ioException e) {e.printStackTrace (); }}}} Lorsque ce code est exécuté, nous constaterons qu'une copie de "test.txt" a été copiée avec succès dans le disque E. Ce code est très simple, la seule chose à dire est:
Nous voyons que nous définissons le BUF, c'est-à-dire que la taille du tampon est 1, ce qui signifie en fait que chaque fois que nous lisons, nous lisons un octet de données (c'est-à-dire 1 lettre d'anglais).
Maintenant, simulons le comportement des interruptions de lecture et d'écriture. Nous permettons le code précédent comme suit:
Importer java.io.file; import java.io.fileInputStream; import java.io.filenotfoundException; import java.io.fileoutputStream; import java.io.ioException; import java.io.randomAccessfile; test public test {private static int position = -1; public static void main (String [] args) {// Source and Target Fichiers Fichier SourceFile = nouveau fichier ("d: /", "test.txt"); File TargetFile = nouveau fichier ("e: /", "test.txt"); // Stream d'entrée et de sortie FileInputStream fis = null; FileoutputStream fos = null; // Byte de tampon de données [] buf = nouveau octet [1]; try {fis = new FileInputStream (sourcefile); fos = new FileOutputStream (TargetFile); // Données lire et écrire while (fis.read (buf)! = -1) {fos.write (buf); // Lorsque 3 octets de contenu de fichier ont été téléchargés, le réseau interrompt et une exception est lancée si (cibleFile.Length () == 3) {position = 3; lancer un nouveau fileAccessException (); }}} catch (fileAccessException e) {keepging (sourcefile, targetfile, position); } catch (filenotfoundException e) {System.out.println ("Spécifier le fichier n'existe pas"); } catch (ioException e) {// todo: gère l'exception} enfin {try {// ferme le flux d'entrée et de sortie if (fis! = null) fis.close (); if (fos! = null) fos.close (); } catch (ioException e) {e.printStackTrace (); }}} private static void Keeping (source de fichier, cible de fichier, position int) {try {thread.sleep (10000); } Catch (InterruptedException e) {// TODO Block de catch généré automatiquement e.printStackTrace (); } try {randomaccessfile readFile = new randomaccessfile (source, "rw"); RandomAccessFile WriteFile = new RandomAccessFile (Target, "RW"); readFile.seek (position); writeFile.seek (position); // Byte de tampon de données [] buf = nouveau octet [1]; // Données à lire et à écrire while (readFile.read (buf)! = -1) {writeFile.Write (buf); }} catch (filenotfoundException e) {// TODO Block de catch généré automatiquement e.printStackTrace (); } catch (ioException e) {// TODO Bloc de capture généré automatiquement e.printStackTrace (); }}} classe FileAccessException étend une exception {}Pour résumer, quel travail nous avons fait dans ce changement:
• Premièrement, nous définissons une position variable pour enregistrer l'emplacement où la lecture et l'écriture ont été terminées lorsqu'une interruption se produit. (C'est pour plus de commodité. En fait, il convient de dire que cette valeur doit être stockée dans un fichier ou une base de données pour la persistance)
• Ensuite, dans la boucle While de la lecture et de l'écriture de fichiers, nous simulons l'occurrence d'un comportement d'interruption. Ici, lorsque la longueur du fichier du fichier cible est de 3 octets, il simule le lancement d'une exception que nous avons personnalisée. (Nous pouvons imaginer que dans le téléchargement réel, le contenu des octets "X" a été téléchargé (téléchargé) et le réseau est interrompu pour le moment, nous enregistrerons donc "X" dans l'exception lancée par l'interruption du réseau).
• Le reste est comme nous l'avons dit auparavant, après le début du comportement de la "continuation", nous traversons notre fichier via la classe RandomAccessFile, puis spécifions le pointeur vers l'emplacement où l'interruption précédente s'est produite pour la lecture et l'écriture via Seek.
(Pour le téléchargement et le téléchargement de fichiers réels, nous devons bien sûr télécharger la valeur d'interruption enregistrée sur le serveur. Cette méthode est généralement httpconnection.setRequestProperty ("plage", "bytes = x");)
Dans notre code, activez le comportement "continu", c'est-à-dire la méthode Keeping: nous commençons à laisser le fil dorment pendant 10 secondes, ce qui est précisément pour nous permettre d'exécuter le programme et de voir l'effet.
Maintenant que nous exécutons le programme, le fichier commencera le "processus de téléchargement du disque D vers le disque". Tout d'abord, nous cliquons sur le disque E et constatons qu'il existe en effet un fichier Test.txt supplémentaire. Ouvrez-le et trouvez le contenu comme suit:
C'est vrai, à ce moment-là, nous avons constaté que le contenu n'a que "ABC". Ceci est dans nos attentes, car notre simulation de programme interrompt lorsque le fichier est téléchargé par 3 octets.
Ok, attendons tranquillement 10 secondes pour passer, puis cliquez sur le fichier pour voir s'il peut réussir:
Grâce à des captures d'écran, nous avons constaté que le contenu est en effet devenu "ABC", et donc la continuation a été achevée.
Ce qui précède est tout le contenu de cet article. J'espère que cela sera utile à l'apprentissage de tous et j'espère que tout le monde soutiendra davantage Wulin.com.