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


  • Mod

    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 00

    Ich 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).aspx

    Edit:
    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


Anmelden zum Antworten