C++ écrire dans un ficher txt en format MS-DOS

Résolu
flayaya - 15 janv. 2013 à 13:46
BruNews Messages postés 21040 Date d'inscription jeudi 23 janvier 2003 Statut Modérateur Dernière intervention 21 août 2019 - 18 janv. 2013 à 12:51
Bonjour,


Je crée un batch depuis un programe Qt,

création d'un fichier .bat,

écriture dans le fichier,

fermeture du fichier puis exécution du fichier.
Est-il possible comme dans WordPad de sauvegarder ce fichier en "Document texte MS-DOS" et non en document texte ?

J'utilise cette méthode trouvé dans une FAQ,
http://qt.developpez.com/faq/?page=modules-qtcore-fichiers-lectureecriture

// Création d'un objet QTextStream à partir de notre objet QFile
QTextStream flux(&file);
// On choisit le codec correspondant au jeu de caractère que l'on souhaite ; ici, UTF-8
flux.setCodec("UTF-8");
// Écriture des différentes lignes dans le fichier
flux << "Bonjour," << endl << "Nous sommes le " << 3 << " avril " << 2009 << endl;


Je suppose qu'il faut changer "UTF-8" par un autre format mais le quel?

Sinon il y a t'il une autre méthode?

Merci d'avance pour vos réponses

18 réponses

Je crois que cette fois c'est bon

#include <string>
#include <cstring>
#include 
#include <windows.h>
#include <fstream>

int main()
{
    std::ifstream fichier("test.txt");//fichier a convertir
        if (!fichier)
        {
        std::cerr << "Error" << std::endl;
        return 1;
        }

    std::string monTexte;
    getline( fichier, monTexte );

    //conversion du string en char
    size_t size = monTexte.size() + 1;
    char * buffer = new char[ size ];
    strncpy( buffer, monTexte.c_str(), size );

    //conversion
    CharToOem(buffer, buffer);

    //enregistrement
    std::ofstream fichier2("test2.txt",std::ios::app); //fichier converti
        if (!fichier2)
        {
        std::cerr << "Error" << std::endl;
        return 1;
        }
    fichier2.write(buffer, size);

    //libérer la mémoire
    delete [] buffer;

 return 0;
}


sa te parais bon ?
3
cptpingu Messages postés 3837 Date d'inscription dimanche 12 décembre 2004 Statut Modérateur Dernière intervention 28 mars 2023 123
15 janv. 2013 à 14:00
Bonjour.

On peut bien évidemment choisir son format de fichier.
Voici une aide illustrée (en anglais, même si tu ne parles pas anglais, avec les images tu devrais t'en sortir):
https://www.developer.nokia.com/Community/Wiki/About_Encoding_of_Qt_Creator
http://stackoverflow.com/questions/10038905/how-to-set-default-file-encoding-of-source-file-in-qt-creator

________________________________________________________________________
Historique de mes créations, et quelques articles:
[ http://0217021.free.fr/portfolio http://0217021.free.fr/portfolio]
Merci d'utiliser Réponse acceptée si un post répond à votre question
0
Tout d'abord merci de votre réponse rapide

Je me suis peut-être mal exprimer.
votre méthode permet de changer l'encodage de toute une page dans qt. (si je ne me trompe pas)

Mon programme va créer un .bat dont j’aimerai changer l'encodage.

je me sent un peut perdu devant cette longue liste d'encodage possible, le quel correspondrai a la fonction de wordpad sauvegarder ce fichier en "Document texte MS-DOS" ?

je suppose qu'il faudrait changer
flux.setCodec("UTF-8");

par l'encodage adéquate ?
0
cptpingu Messages postés 3837 Date d'inscription dimanche 12 décembre 2004 Statut Modérateur Dernière intervention 28 mars 2023 123
15 janv. 2013 à 15:45
Effectivement, j'avais mal compris ta question. Suite à ta précision, j'ai maintenant mieux compris celle-ci.

Essaie avec:
flux.setCodec("ISO-8859-1");


________________________________________________________________________
Historique de mes créations, et quelques articles:
[ http://0217021.free.fr/portfolio http://0217021.free.fr/portfolio]
Merci d'utiliser Réponse acceptée si un post répond à votre question
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
Aucun changement.

Sous wordpad, enregistré dans cette encodage, un "à" serra écrit de cette façon "…"(on ne voie qu'un point mais il y en a trois,faire un essaie sous wordpad et choisir enregistré sous, type : Document texte MS-DOS)
(je fais cette précision pour être sure que nous parlions bien du même encodage)

Là mon "à" reste écris "à"

La partie de mon code

QTextStream flux2(&file2);
flux2.setCodec("ISO-8859-1");
flux2 <<  "echo à" <<endl;
file2.close();


J'ai simplifier le contenu du .bat car ceci n'a aucune importance dans se cas

Si le .bat est bien encodé son contenu devrais ressemblé a sa :
echo &#8230;
de même il y a trois point normalement

alors que là le contenu reste :
echo à


J'ai fais quelques autre essaie mais sans réussir...
0
cptpingu Messages postés 3837 Date d'inscription dimanche 12 décembre 2004 Statut Modérateur Dernière intervention 28 mars 2023 123
15 janv. 2013 à 17:48
Je ne connais pas trop l'encoding utilisé dans les batch, mais d'après ceci:
https://en.wikipedia.org/wiki/Code_page_437

Tu pourrais essayer un de ceux-ci (attention non testé):
flux2.setCodec("CP437");
// ou
flux2.setCodec(QCodePage437Codec);


________________________________________________________________________
Historique de mes créations, et quelques articles:
[ http://0217021.free.fr/portfolio http://0217021.free.fr/portfolio]
Merci d'utiliser Réponse acceptée si un post répond à votre question
0
Bon les deux encodage ne change rien.
J'ai l’impression que la ligne
flux2.setCodec("");

ne fonctionne pas comme attendue, il y aurait il moyen de le vérifier ?
0
Je ne trouve pas de fonction éditer désolé pour se double message.

Alors la ligne
.setCodec("");

ne peut avoir que trois types d'encodage et ne fais rien si le type d'encodage n'est pas valide

http://translate.google.fr/translate?hl=fr&sl=en&tl=fr&u=http%3A%2F%2Fdoc.qt.digia.com%2Fqt%2Fqtextstream.html&anno=2


les types valide sont : "ISO 8859-1", "UTF-8","UTF-16".

Sets the codec for this stream to the QTextCodec for the encoding specified by codecName . Common values for codecName include "ISO 8859-1", "UTF-8", and "UTF-16". If the encoding isn't recognized, nothing happens.


Existe t'il d'autre méthode pour changer l'encodage d'un fichier ?
0
cptpingu Messages postés 3837 Date d'inscription dimanche 12 décembre 2004 Statut Modérateur Dernière intervention 28 mars 2023 123
15 janv. 2013 à 20:57
Je ne sais pas.
Essaie de bidouiller avec la fonction "CharToOem".

________________________________________________________________________
Historique de mes créations, et quelques articles:
[ http://0217021.free.fr/portfolio http://0217021.free.fr/portfolio]
Merci d'utiliser Réponse acceptée si un post répond à votre question
0
je pense avoir quelque chose, mais j’obtiens des erreurs a la compilation.

http://h-deb.clg.qc.ca/Sujets/AuSecours/Afficher--Accents.html

j'essaye de compiler se bout de code
#include 
#include <string>
#include <vector>
#include 
#include <windows.h>
std::string FormaterPourConsole(const std::string &src)
{
   using std::vector;
   using std::string;
   using std::begin;
   using std::end;
   vector<char> v(src.size() + 1); // remplit v de '\0' avec espace pour un délimiteur 
   CharToOem(src.c_str(), &v[0]);
   return string(begin(v), end(v));
}
int main()
{
   using std::cout;
   using std::endl;
   cout << FormaterPourConsole("Étonnant?") << endl;
}


l'erreur :
C:\Users\Georges\Desktop\testcomparaison\chartooem\chartooem\main.cpp||In function 'std::string FormaterPourConsole(const std::string&)':|
C:\Users\Georges\Desktop\testcomparaison\chartooem\chartooem\main.cpp|10|error: 'std::begin' has not been declared|
C:\Users\Georges\Desktop\testcomparaison\chartooem\chartooem\main.cpp|11|error: 'std::end' has not been declared|
C:\Users\Georges\Desktop\testcomparaison\chartooem\chartooem\main.cpp|14|error: 'begin' was not declared in this scope|
C:\Users\Georges\Desktop\testcomparaison\chartooem\chartooem\main.cpp|14|error: 'end' was not declared in this scope|
||Build finished: 4 errors, 0 warnings|


je ne comprend pas pourquoi j'obtiens cette erreur.

Quoi qu'il en sois "CharToOem" pourrai être la solution, j'ai un peux de mal a saisir son fonctionnement, mais des test que j'ai fais et de se que j'ai lu il semble que se sois le bon encodage.
Il ne me reste plus qu'a réussir a le faire fonctionné
Si tu as des idées (ou quelqu'un d'autre ) elles sont les bienvenus
0
j'ai oublier de préciser j'ai effectuer mes test sous Codeblocks.

il n'y a pas de fonction editer sur cppfrance
0
Effectivement CharToOem étais la bonne solution
Voilà le code qui permet de convertir un fichier

#include <string>
#include <cstring>
#include 
#include <windows.h>
#include <fstream>

int main()
{
    using namespace std;

    ifstream fichier("test.txt", ios::in);  //fichier a convertir
    string MonTexte;
    getline( fichier, MonTexte );

    //conversion du string en char
    size_t size = MonTexte.size() + 1;
    char * buffer = new char[ size ];
    strncpy( buffer, MonTexte.c_str(), size );

    //conversion
    CharToOem(buffer, buffer);
    //enregistrement
    std::ofstream fichier2("test2.txt", ios::out | ios::app); //fichier converti
    fichier2 <<buffer<<endl;

    //libérer la mémoire
    delete [] buffer;
    //fermer les fichier
    fichier.close();
    fichier2.close();

}


Si tu as des remarques ou amélioration a proposé elle sont les bienvenus
0
cptpingu Messages postés 3837 Date d'inscription dimanche 12 décembre 2004 Statut Modérateur Dernière intervention 28 mars 2023 123
17 janv. 2013 à 14:36
Bonjour.

J'ai effectivement quelques remarques:
- Évite les "using namespace", voir: http://0217021.free.fr/portfolio/axel.berardino/articles/bon-usage-using-namespace (Même si ton using est dans la fonction et pas en dehors, ce qui est déjà pas mal)
- Les majuscules sont réservées aux noms de classe (MonTexte => monTexte)

std::ofstream fichier2("test2.txt", ios::out | ios::app);

Pas besoin de "std::ios::out" puisqu'un un std::ofstream est un "std::fstream" avec l'option "std::ios::out".

fichier2 <<buffer<<endl;

C'est correcte, mais on peut optimiser un peu en écrivant (vu qu'on connait la taille et que l'on ne veut écrire qu'un bloc):
fichier2.write(buffer, size);

//fermer les fichier
fichier.close();
fichier2.close();


Pas nécessaire. Les streams sont des objets qui, lors de leurs destructions, ferment déjà leurs fichiers. Tu peux simplement retirer les instructions closes qui sont automatiques.

Je ne suis pas sur de ceci, mais:

size_t size = MonTexte.size() + 1;
char * buffer = new char[ size ];
strncpy( buffer, MonTexte.c_str(), size );
CharToOem(buffer, buffer);


pourrait être simplifié en:
size_t size = monTexte.size() + 1;
char* buffer = new char[size];
CharToOem(monTexte.c_str(), buffer);
// Dans le cas ou CharToOem ne met pas de 0 terminal:
buffer[size - 1] = 0; // Possiblement inutile.

(Là pour le coup, c'est à tester. Je ne sais ni si ça fonctionne correctement, ni si c'est plus optimisé. Néanmoins, d'après la doc, la 2ème méthode ferait la copie et la traduction, ce qui t'éviterait un parcours inutile).

________________________________________________________________________
Historique de mes créations, et quelques articles:
[ http://0217021.free.fr/portfolio http://0217021.free.fr/portfolio]
Merci d'utiliser Réponse acceptée si un post répond à votre question
0
Normalement c'est bon
#include <string>
#include <cstring>
#include 
#include <windows.h>
#include <fstream>

int main()
{
    std::ifstream fichier("test.txt", std::ios::in);  //fichier a convertir
    std::string monTexte;
    getline( fichier, monTexte );

    //conversion du string en char
    size_t size = monTexte.size() + 1;
    char * buffer = new char[ size ];
    strncpy( buffer, monTexte.c_str(), size );

    //conversion
    CharToOem(buffer, buffer);
    //enregistrement
    std::ofstream fichier2("test2.txt",std::ios::app); //fichier converti
    fichier2.write(buffer, size);

    //libérer la mémoire
    delete [] buffer;

}


Merci pour la lecture sur les using namespace je vais essayé de passer cette mauvaise habitude.

Pour une raison que je ne comprend pas cette solution
size_t size = monTexte.size() + 1;
char* buffer = new char[size];
CharToOem(monTexte.c_str(), buffer);
// Dans le cas ou CharToOem ne met pas de 0 terminal:
buffer[size - 1] = 0; // Possiblement inutile.

change l'encodage

Je conserve donc ma première version qui ne pause pas de problème.

Merci pour ton aide et tes remarques pertinentes
0
cptpingu Messages postés 3837 Date d'inscription dimanche 12 décembre 2004 Statut Modérateur Dernière intervention 28 mars 2023 123
17 janv. 2013 à 16:41
Oh je n'avais pas vu deux-trois petits trucs:

std::ifstream fichier("test.txt", std::ios::in);

Même remarque. Un "std::ifstream" c'est déjà un "std::fstream" avec "std::ios::in". Tu peux directement écrire: std::ifstream fichier("test.txt");

Lorsque tu ouvres ou veut écrire dans un fichier, il faut tester, si ça a réussi:
std::ifstream fichier("test.txt");
if (!fichier)
{
  std::cerr << "Error" << std::endl;
  return 1;
}

Cette même remarque s'applique aussi à ton std::ofstream.

Enfin, la fonction "main" *doit* retourner quelque chose (Il manque un return 0). En effet, le code de retour peut être utilisé par le système d'exploitation. (0 voulant dire: pas d'erreur).

________________________________________________________________________
Historique de mes créations, et quelques articles:
[ http://0217021.free.fr/portfolio http://0217021.free.fr/portfolio]
Merci d'utiliser Réponse acceptée si un post répond à votre question
0
cptpingu Messages postés 3837 Date d'inscription dimanche 12 décembre 2004 Statut Modérateur Dernière intervention 28 mars 2023 123
17 janv. 2013 à 17:27
sa te parais bon ?

Oui tout me paraît bon. Aucun souci.

Si tu veux aller plus loin et corriger des petits détails mineurs:
- Les messages d'erreurs pourraient être plus détaillés (raison de l'erreur, nom du fichier à ouvrir qui a échoué, etc...)
- Les commentaires pourraient être un peu plus pertinent (voir: http://0217021.free.fr/portfolio/axel.berardino/articles/ecrire-de-bons-commentaires)

(Petit hors sujet, vu que tu fais souvent la faute: "sa" marque la possession. Ex: sa voiture. Astuce: on pourrait remplacer par "ta", ou "la". En revanche, "ça" marque la démonstration, c'est le diminutif de "cela" ou "ceci". Astuce: on pourrait dire: cela/ça te parait bon ?)

________________________________________________________________________
Historique de mes créations, et quelques articles:
[ http://0217021.free.fr/portfolio http://0217021.free.fr/portfolio]
Merci d'utiliser Réponse acceptée si un post répond à votre question
0
Merci pour toutes tes réponses
0
BruNews Messages postés 21040 Date d'inscription jeudi 23 janvier 2003 Statut Modérateur Dernière intervention 21 août 2019
18 janv. 2013 à 12:51
Salut vous 2,

je n'ai surtout pas envie de lancer quelque troll que ce soit, c'est juste pour présenter un autre point de vue à flayaya.

Que le code soit syntaxiquement correct et fasse le boulot, j'admets à 100% pour au moins 2 raisons:
1) Je ne pratique pas les ++eries.
2) CptPingu le valide.

Ceci étant admis, je présente mon point de vue.
L'utilisation de surcouches (stream, string, ...) quand on finit par appeler l'API, inutile et donc nuisible.
Pourquoi nuisible:
1) Exe inutilement énorme (on embarque les surcouches dans l'exe).
2) Contre performant puisque les surcouches finissent en appels API, autant le faire directement.
3) Aucun besoin de recopie (string vers tableau buffer).
etc, etc.

Il est clair que vu le taf demandé au prog, aucun problème de perfs ici mais c'est pour une réflexion plus large sur la tournure que prend l'informatique. Nous disposons de CPUs et autres composants très performants et je les vois amusés à des contorsions stériles avant d'aller au but final. Avoir des I7 pour obtenir le résultat qu'on aurait avec un Pentium 133 et du vrai code, c'est désolant, quel gachis.
Le code que je mets plus bas se résume en 15 lignes hors déclarations.
Exe obtenu fait 3 Ko et efficacité optimale. On peut constater que ce n'est en rien plus difficile à écrire que quelque autre méthode. Je peux assurer que je ne mets pas plus de temps à l'écrire que celui qui utilisera du STD et autres biniouteries.
J'exclus direct le discours "portabilté", ça n'a jamais existé et aucun espoir que ça existe un jour. Un prog finit toujours par appeler l'API du système ciblé, aucune surcouche ne couvrira jamais tout le système quel qu'il soit.


#include <windows.h>
#define ONEPAGE   4096
#define MEMDISPO  (MEM_COMMIT | MEM_RESERVE)
#define mcVirtualAlloc(N) VirtualAlloc(0, N, MEMDISPO, PAGE_READWRITE);
#define mcVirtualFree(Addr) VirtualFree(Addr, 0, MEM_RELEASE);

char szappname[] = "chrOem";
char szFL[] = "D:\\chrOem.txt";

void __fastcall myWinMain()
{
  void *pmem;
  HANDLE hfl;
  UINT64 size;
  DWORD rw;
  LARGE_INTEGER li;
  DWORD flagMSG = 0x30;
  hfl = CreateFile(szFL, GENERIC_READ | GENERIC_WRITE, 0, 0,
                   OPEN_EXISTING, 0, 0);
  if(hfl == INVALID_HANDLE_VALUE) goto goMSG;
  if(!GetFileSizeEx(hfl, (PLARGE_INTEGER) &size)) goto closeFL;
  if(!size) goto closeFL;             // FICHIER VIDE
  if(size > ONEPAGE*8) goto closeFL;  // > 32 Ko, BIZZARE POUR UN BATCH
  
  // LECTURE ET ECRITURE SE FAIT SUR UN BUFFER ALIGNE SUR PAGE MEMOIRE
  // ON VEUT UN ZERO FINAL DE CHAINE POUR CharToOem() DONC size+1
  pmem = mcVirtualAlloc(size + 1);
  if(!pmem) goto closeFL;
  ReadFile(hfl, pmem, (DWORD) size, &rw, 0);
  if(rw != (DWORD) size) goto relMEM; // ERREUR LECTURE
  
  CharToOem(pmem, pmem);
  
  li.QuadPart = 0;
  SetFilePointerEx(hfl, li, 0, FILE_BEGIN);
  WriteFile(hfl, pmem, (DWORD) size, &rw, 0);
  if(rw != (DWORD) size) goto relMEM; // ERREUR ECRITURE
  
  flagMSG = 0x40;   // BOULOT EST FINI OK
relMEM:
  mcVirtualFree(pmem);
closeFL:
  CloseHandle(hfl);
goMSG:
  MessageBox(0, szFL, szappname, flagMSG);
  ExitProcess(0);
}


ciao...
0
Rejoignez-nous