Problem mit Datei-auslesen, verarbeiten, senden (std::string zu int)
-
Hallo miteinander
Ich habe gerade ein kleines Problem, bei dem ich irgendwie nicht so recht weiss, wie ich es lösen muss, respektive was nicht läuft:
Ich habe ein paar Vektoren, in denen ich die Datei-Informationen speichere:
static std::vector< std::string > x_achse; static std::vector< std::string > y_achse; static std::vector< std::string > blue; static std::vector< std::string > green; static std::vector< std::string > red;
Das Auslesen der Werte (liegen im Hex-Format vor), und verarbeiten mache ich so:
std::vector< std::string > allItems; // Dynamisches Array std::string item; // File-Dialog OpenFileDialog ^ openFileDialog1 = gcnew OpenFileDialog(); openFileDialog1->InitialDirectory = "C:\\"; openFileDialog1->Filter = "ILDA Files|*.ild"; openFileDialog1->Title = "Select a ILDA File"; // Show the Dialog. // If the user clicked OK in the dialog and // a .ild file was selected, open it. if (openFileDialog1->ShowDialog() == System::Windows::Forms::DialogResult::OK){ labelILDA_pfad->Text = openFileDialog1->FileName; // System::String^ Umwandlung zu const char* String^ orig_pfad = openFileDialog1->FileName; IntPtr strptr = (System::Runtime::InteropServices::Marshal::StringToHGlobalAnsi(orig_pfad)); const char* new_pfad = (const char*)strptr.ToPointer(); std::ifstream fin(new_pfad); // Eingabedatei if(fin.good()){ // Wenn die Datei geöffnet werden konnte x_achse.erase(x_achse.begin(), x_achse.end()); // Vektoren löschen y_achse.erase(y_achse.begin(), y_achse.end()); red.erase(laser_red.begin(), laser_red.end()); green.erase(laser_green.begin(), laser_green.end()); blue.erase(laser_blue.begin(), laser_blue.end()); fin.seekg(0L, ios::beg); // an den Anfang der Datei springen while( getline( fin, item)){ // Zeilenweise Auslesen allItems.push_back(item); // Zeile in Vector speichern } allItems[0].erase(allItems[0].begin(),allItems[0].begin() + 32); // Ersten 32 Zeichen löschen (ILDA-Header) allItems[0].erase(allItems[0].size() - 32,allItems[0].size()); // Lesten 32 Zeichen löschen (ILDA-Header) for(size_t q = 0; q < allItems[0].size(); (q += 8) ){ x_achse.push_back( allItems[0].substr(q, 2) ); // 16Bit X-Achse y_achse.push_back( allItems[0].substr(q + 2, 2) ); // 16Bit Y-Achse blue.push_back( allItems[0].substr(q + 5, 1) ); // 8Bit Blau green.push_back( allItems[0].substr(q + 6, 1) ); // 8Bit Grün red.push_back( allItems[0].substr(q + 7, 1) ); // 8Bit Rot } loadToolStripMenuItem->Tag = "1"; // File geladen } fin.close(); System::Runtime::InteropServices::Marshal::FreeHGlobal(strptr); // Pointer wieder freilassen }
bis heir läuft alles einigermassen gut. Ich habe die entsprechenden Werte in den Verschiedenen Arrays.
Aber danach beim erneuten zusammenstellen und senden (über USB, FTD2XX.dll) kriege ich nie die Werte, die eigentlich in den Arrays sein sollten.if((buttonStart->Tag == "1") && (loadToolStripMenuItem->Tag == "1")){ static int first = 1; // Start-Werte senden static int ComStart = 0; if(ComStart == 0){ FT_GetStatus(ftHandle,&RxBytes,&TxBytes,&EventDWord); if (RxBytes > 0) { // Bytes emfpangen ftStatus = FT_Read(ftHandle,ENQ_Buffer,RxBytes,&BytesReceived); if (ftStatus == FT_OK) { // Lesen ok // FT_Read successful } else { // FT_Read Failed } } } if((ENQ_Buffer[0] == ENQ) || (ComStart == 1) || (first == 1)){ int temp_num = 0; if(first == 1){ // Ersten Werte wurden gesendet first = 0; NUM *= 2; // Beim ersten mahl 1000 Punkte senden } switch (step){ case 0: // Werte zusammenstellen for(i = 2; i < NUM; i += 6){ buffer[i] = atoi(red[last_point].c_str());// C-String zu Int konvertieren buffer[i + 1] = atoi(green[last_point].c_str()); buffer[i + 2] = atoi(blue[last_point].c_str()); buffer[i + 3] = ( (__int8)((atoi(x_achse[last_point].c_str()) & 0x0FFF) >> 4) ); buffer[i + 4] = ( ((__int8)((atoi(x_achse[last_point].c_str()) & 0x000F) << 4 )) | ((__int8)(atoi(y_achse[last_point].c_str()) >> 8)) ); buffer[i + 5] = ( (__int8)(atoi(y_achse[last_point].c_str()) & 0xFF) ); if( last_point == (x_achse.size() - 1) ){ // Ring-System beim Vector last_point = 0; } else{ last_point ++; } } TxBuffer[0] = ENQ; ftStatus = FT_Write(ftHandle, TxBuffer, 1, &BytesWritten); if (ftStatus == FT_OK) { // FT_Write OK step ++; ComStart = 1; } else{ // FT_Write Failed } // break; case 1: // ACK abwarten, Frame starten FT_GetStatus(ftHandle,&RxBytes,&TxBytes,&EventDWord); if (RxBytes > 0) { // Bytes emfpangen ftStatus = FT_Read(ftHandle,RxBuffer,RxBytes,&BytesReceived); if (ftStatus == FT_OK) { // Lesen ok if(RxBuffer[0] == ACK){ // ACK empfangen? TxBuffer[0] = SOH; // SOH und CMD senden TxBuffer[1] = STREAM; ftStatus = FT_Write(ftHandle, TxBuffer, 2, &BytesWritten); if (ftStatus == FT_OK) { // FT_Write OK step ++; } else{ // FT_Write Failed } } } else { // FT_Read Failed } } break; case 2: // Settings senden temp_num = System::Convert::ToByte(NUM >> 8); buffer[0] = temp_num; buffer[1] = System::Convert::ToByte(NUM & 0xFF); ftStatus = FT_Write(ftHandle, TxBuffer, (2 + NUM), &BytesWritten); if (ftStatus == FT_OK) { // FT_Write OK // step =4; } else{ // FT_Write Failed } break; case 3: // ACK abwarten, Frame beenden FT_GetStatus(ftHandle,&RxBytes,&TxBytes,&EventDWord); if (RxBytes > 0) { // Bytes emfpangen ftStatus = FT_Read(ftHandle,RxBuffer,RxBytes,&BytesReceived); if (ftStatus == FT_OK) { // Lesen ok if(RxBuffer[0] == ACK){ // ACK empfangen? TxBuffer[0] = ACK; // Frame beenden TxBuffer[1] = EOT; ftStatus = FT_Write(ftHandle, TxBuffer, 2, &BytesWritten); if (ftStatus == FT_OK) { // FT_Write OK step = 0; // Protokollstatus zurücksetzen if(ComStart == 1){ // Kommunikation beendet ComStart = 0; } for(i = 0; i < NUM + 2; i ++){ // TxBuffer löschen buffer[i] = 0; } } else{ // FT_Write Failed } } else{ // Fehler bei der Übertragung step = 3; } } else { // FT_Read Failed } } break; } } }
Ich kriege keine Fehlermeldung beim Compilieren, aber irgendwie ist jede Array mit irgendetwas gefüllt.
Ich vermute, dass der Fehler irgendwo beim Konvertieren von std::string zu integer ein Fehler passiert.Könnt ihr mir da weiterhelfen?
Besten Dank im voraus
MFG
P51D
-
Vermeide dieses fürchterliche Mischmasch von managed und Nativem Code.
-
Dieser Thread wurde von Moderator/in Martin Richter aus dem Forum MFC (Visual C++) in das Forum C++/CLI mit .NET verschoben.
Im Zweifelsfall bitte auch folgende Hinweise beachten:
C/C++ Forum :: FAQ - Sonstiges :: Wohin mit meiner Frage?Dieses Posting wurde automatisch erzeugt.
-
Martin Richter schrieb:
Vermeide dieses fürchterliche Mischmasch von managed und Nativem Code.
Was meinst du damit?
MFG
P51D
-
stdt::vector is native und fast alles andere ist managed.... das holt Dich früher oder später ein, da Du diesen Code fast nicht mehr warten kannst...
Verwende anstelle std::vector bitte Generic::List
-
Hallo miteinander
Ich habe jetzt mal versucht, das ganze etwas umzuschreiben und schon habe ich wieder ein Problem:
Das Einlesen funktioniert nicht mehr, und ich habe leider keine Ahnung, wie ich dies beheben könnte:std::string item; Generic::List<char> allItems; while(getline(fin,item)){ allItems.Add(item.c_str()); } allItems.RemoveRange(0,32); allItems.RemoveRange(allItems.Capacity()-32,allItems.Capacity()); for(size_t q = 0; q < allItems.Capacity(); q ++){ //Ausgabe, Test-File fout << allItems[q]; }
1. Konvertierung von string zu char ergibt Fehler
2. ersten und letzt 32 Zeichen löschen funktioniert nicht (out of Range, das kann aber nicht sein)
3. fout hat nur gerade 00Ich möchte eigentlich eine einfache Funktion, die Hex-Werte aus einer Datei (Binär-Format) ausliest, diese verarbeitet (löschen) und dann auf weitere Arrays verteilt. Am Schluss wäre es praktisch, wenn ich die Werte in char oder int8 Format hätte, aber ich seh da nicht wirklich durch.
Ich währe froh, wenn mir jemand etwas auf die Sprünge helfen könnte. Das einzige Problem ist das File-Handling, da ich hier leider praktisch keine Erfahrung habe. Der Rest mit dem senden ist dann nicht mehr so schwierig.
MFG
P51D
-
Wenn Du List<..> verwendest, dann natürlich nicht mit std::getline(..).
Ausserdem gibt es bereits eine vorgefertigte Möglichkeit eine Datei Binär in ein Byte Array einzulesen:
http://msdn.microsoft.com/de-de/library/system.io.file.readallbytes(v=VS.80).aspxEdit:
Ausserdem solltest Du Dir klar darüber werden was der Unterschied zwischen List<..>::Capacity und List<..>::Count ist.
-
ok, mitlerweile habe ich ca 90% der Einlesefuktion und etwa 30% der Kommunikation neu geschrieben, aber das Problem ist nach wie vor das allte:
Ich bekomme beim MCU nicht die Werte, die ich am PC habe. Die einzige unbekannte dazwischen ist der FTD2xx.dll-Teil.
Im groben und ganzen funktioniert auch alles, nur sobald ich den Stream starte stimmen die Werte nicht mehr.public: System::Collections::Generic::List<unsigned int> x_achse; public: System::Collections::Generic::List<unsigned int> y_achse; public: System::Collections::Generic::List<unsigned char> red; public: System::Collections::Generic::List<unsigned char> green; public: System::Collections::Generic::List<unsigned char> blue; // File-Dialog OpenFileDialog ^ openFileDialog1 = gcnew OpenFileDialog(); openFileDialog1->InitialDirectory = "C:\\"; openFileDialog1->Filter = "ILDA Files|*.ild"; openFileDialog1->Title = "Select a ILDA File"; // Show the Dialog. // If the user clicked OK in the dialog and // a .ild file was selected, open it. if (openFileDialog1->ShowDialog() == System::Windows::Forms::DialogResult::OK){ labelILDA_pfad->Text = openFileDialog1->FileName; // System::String^ Umwandlung zu const char* String^ orig_pfad = openFileDialog1->FileName; // Datei in Byte-Array lesen array<unsigned char> ^ buffer = System::IO::File::ReadAllBytes(orig_pfad); if(buffer->Length != 0){ laser_red.Clear(); // Delete Lists laser_green.Clear(); laser_blue.Clear(); x_achse.Clear(); y_achse.Clear(); for(size_t q = 32; q < buffer->Length-32; (q += 8)){ // Listen mit entsprechenden Werten versehen x_achse.Add(((buffer[q] & 0xF) << 8) | buffer[q + 1]); y_achse.Add(((buffer[q + 2] & 0xF) << 8) | buffer[q + 3]); blue.Add(buffer[q + 5]); green.Add(buffer[q + 6]); red.Add(buffer[q + 7]); } File_info->Text = "File good"; loadToolStripMenuItem->Tag = "1"; } else{ File_info->Text = "File error"; } } static int NUM = 400 * 6; int i = 0; // Durchlaufsvarible um Werte zu senden static int last_point = 0; // Pointer für Vectorenzugriff static char buffer[4850]; char TxBuffer[20]; char RxBuffer[20]; char ENQ_Buffer[10]; static int step = 0; // Kom-Protokoll Schritt /* Streaming */ if((buttonStart->Tag == "1") && (loadToolStripMenuItem->Tag == "1")){ static int first = 1; // Start-Werte senden static int ComStart = 0; if(ComStart == 0){ FT_GetStatus(ftHandle,&RxBytes,&TxBytes,&EventDWord); if (RxBytes > 0) { // Bytes emfpangen ftStatus = FT_Read(ftHandle,ENQ_Buffer,RxBytes,&BytesReceived); if (ftStatus == FT_OK) { // Lesen ok // FT_Read successful } else { // FT_Read Failed } } } if((ENQ_Buffer[0] == ENQ) || (ComStart == 1) || (first == 1)){ int temp_num = 0; if(first == 1){ // Ersten Werte wurden gesendet first = 0; NUM *= 2; // Beim ersten mahl doppelte Punkte senden } switch (step){ case 0: // Werte zusammenstellen buffer[0] = NUM >> 8; buffer[1] = (NUM & 0xFF); for(i = 2; i < NUM; i += 6){ buffer[i] = red[last_point]; buffer[i + 1] = green[last_point]; buffer[i + 2] = blue[last_point]; buffer[i + 3] = (x_achse[last_point] >> 4); buffer[i + 4] = ( ((x_achse[last_point] & 0xF) << 4 ) | (y_achse[last_point] >> 8) ); buffer[i + 5] = (y_achse[last_point] & 0xFF ); if(last_point == x_achse.Count - 1) last_point = 0; else last_point ++; } TxBuffer[0] = ENQ; ftStatus = FT_Write(ftHandle, TxBuffer, 1, &BytesWritten); if (ftStatus == FT_OK) { // FT_Write OK step ++; ComStart = 1; L_info->Text = "ENQ"; } else{ // FT_Write Failed } break; case 1: // ACK abwarten, Frame starten FT_GetStatus(ftHandle,&RxBytes,&TxBytes,&EventDWord); if (RxBytes > 0) { // Bytes emfpangen ftStatus = FT_Read(ftHandle,RxBuffer,RxBytes,&BytesReceived); if (ftStatus == FT_OK) { // Lesen ok if(RxBuffer[0] == ACK){ // ACK empfangen? TxBuffer[0] = SOH; // SOH und CMD senden TxBuffer[1] = STREAM; ftStatus = FT_Write(ftHandle, TxBuffer, 2, &BytesWritten); if (ftStatus == FT_OK) { // FT_Write OK step ++; L_info->Text = "START Frame"; } else{ // FT_Write Failed } } } else { // FT_Read Failed } } break; case 2: // Settings senden ftStatus = FT_Write(ftHandle, TxBuffer, (2 + NUM), &BytesWritten); if (ftStatus == FT_OK) { // FT_Write OK step ++; label2->Text = BytesWritten.ToString(); label1->Text = System::Convert::ToString((buffer[0] << 8) | buffer[1]); } else{ // FT_Write Failed } break; case 3: // ACK abwarten, Frame beenden FT_GetStatus(ftHandle,&RxBytes,&TxBytes,&EventDWord); if (RxBytes > 0) { // Bytes emfpangen ftStatus = FT_Read(ftHandle,RxBuffer,RxBytes,&BytesReceived); if (ftStatus == FT_OK) { // Lesen ok if(RxBuffer[0] == ACK){ // ACK empfangen? TxBuffer[0] = ACK; // Frame beenden TxBuffer[1] = EOT; ftStatus = FT_Write(ftHandle, TxBuffer, 2, &BytesWritten); if (ftStatus == FT_OK) { // FT_Write OK step = 0; // Protokollstatus zurücksetzen if(ComStart == 1){ // Kommunikation beendet ComStart = 0; } for(i = 0; i < NUM + 2; i ++){ // TxBuffer löschen buffer[i] = 0; } //L_info->Text = "END Frame"; } else{ // FT_Write Failed } L_info->Text = "ACK"; } else{ // Fehler bei der Übertragung step = 3; } } else { // FT_Read Failed } } break; } } }
label2 hat 4802 und label1 4800. Beim Mikrocontroller empfange ich aber als NUM den Wert 16633 und bei den Parametern irgendetwas (bei x_achse[0] wäre es 0).
Das der FTDI Probleme macht respektive der Treiber kann ich mir nicht vorstellen, da das Protokoll bis zu der Stream-Array richtig funktioniert.
EDIT:
Copy-Past-Fehler:case 2: // Settings senden ftStatus = FT_Write(ftHandle, TxBuffer, (2 + NUM), &BytesWritten); if (ftStatus == FT_OK) { // FT_Write OK step ++; label2->Text = BytesWritten.ToString(); label1->Text = System::Convert::ToString((buffer[0] << 8) | buffer[1]); } else{ // FT_Write Failed } break;
Da sollte eigentlich nicht TxBuffer sonder buffer gesendet werden. Tja, so schnell gehts.
Jetzt stellt sich aber ein neues Problem:
Die Timer-Funktion der Kommunikation (interval = 1) wird zu langsam aufgerufen, so dass höchsten 1-3 mal die Werte gesendet werden, befor sich der RxBuffer falsch verhält.
Die 4802 Bytes werden beim MCU in ~18.8 Milisekunden entgegengenommen und verarbeitet. Das ganze Protokoll beansprucht aber interessanterweise etwa 56ms. Für ca 6 Bytes mehr wird da eine Verzögerung generiert, in der ich etwa nochmal 6000 Bytes senden könnte?
Gibt es eine Möglichkeit, dass eine Funktion von Windows etwa alle 500 us aufgerufen wird? Damit das Problem dort schon mal beseitigt wäre. Ich weiss leider aber nicht, wo dann die enorme Verzögerung generiert wird: Windows, FTD2xx oder FTDI. Beim MCU bin ich mir sicher, dass dieser auf maximalem Speed arbeitet.Hat jemand eine Idee?
Besten Dank für die Hilfe
MFG
P51D
-
Ich habe das "Problem" ziemlich bis auf den FTD2xx Treiber einschränken können, da selbst bei einer for- oder while-Schlaufe das Streaming nur maximal 8-10 mal ausgeführt wird (selbst mit einem backgroundworker).
Es scheint so, als wäre der Treiber ein klein wenig langsam wenn es um einzelne Bytes lesen oder schreiben geht, aber sobalt eine grosse Menge (> 1kByte) auf einmal gesendet werden soll, ist er dann wirkich schnell.
Oder wie kann sich jemand die Verzögerung erklähren?
Besten Dank für die Unterstützung
P51D