Autore Topic: file.readline COME Leggere l'ultima riga?  (Letto 501 volte)

Offline allegfede

  • Gran Maestro dei Gamberi
  • *****
  • Post: 738
    • Mostra profilo
file.readline COME Leggere l'ultima riga?
« il: 06 Ottobre 2016, 14:54:53 »
Codice: [Seleziona]
Public Sub Timer_Encode_status_Timer()
Dim Testo As String

  If Exist(FileChooser_Destinazione.Dir & "/MFRfile.txt") Then
    Try testo = hEncoderStatFile.ReadLine
    Label_statistiche.Text = Testo
  Endif
 
End

leggo il file delle statistiche di codifica, ma l'ultima riga e' quella con lo status corrente.

Posso fare un tail che voi sappiate?
se corri, morirai stanco (motto degli sniper)

Online vuott

  • Moderatore globale
  • Senatore Gambero
  • *****
  • Post: 11.284
  • Ne mors quidem nos iunget
    • Mostra profilo
Re:file.readline COME Leggere l'ultima riga?
« Risposta #1 il: 06 Ottobre 2016, 14:59:52 »
Perdona, ma non ho capito se del file di testo l'ultima riga viene o non viene letta. In caso negativo, per quale ragione non viene letta.

Inoltre, vorrei capire perché sei costretto ad usare Try .
« Chiunque, non ricorrendo lo stato di necessità, nel proprio progetto Gambas fa uso delle istruzioni Shell o Exec, è punito con la sanzione pecuniaria da euro 20,00 a euro 60,00. »

Offline allegfede

  • Gran Maestro dei Gamberi
  • *****
  • Post: 738
    • Mostra profilo
Re:file.readline COME Leggere l'ultima riga?
« Risposta #2 il: 06 Ottobre 2016, 15:23:15 »
qualche volta il file viene letto prima di essere stato scritto ... dipende da quanto e' voloce ffmpeg ... cosi' faccio prima :D

poi in genere la prima riga e' vuota e poi ffmpeg inizia a scrivere righe cosi':
Citazione
frame= 36366 q= -0.0 f_size=     55 s_size=    70893kB time= 1454.600 br=    11.0kbits/s avg_br=   399.3kbits/s type= ?
frame= 36367 q= -0.0 f_size=     59 s_size=    70893kB time= 1454.640 br=    11.8kbits/s avg_br=   399.2kbits/s type= ?
frame= 36368 q= -0.0 f_size=     54 s_size=    70893kB time= 1454.680 br=    10.8kbits/s avg_br=   399.2kbits/s type= ?
frame= 36368 q= -0.0 f_size=     52 s_size=    70893kB time= 1454.720 br=    10.4kbits/s avg_br=   399.2kbits/s type= ?
frame= 36368 q= -0.0 f_size=     59 s_size=    70893kB time= 1454.760 br=    11.8kbits/s avg_br=   399.2kbits/s type= ?
frame= 36368 q= -0.0 f_size=     53 s_size=    70893kB time= 1454.800 br=    10.6kbits/s avg_br=   399.2kbits/s type= ?
frame= 36368 q= -0.0 f_size=     52 s_size=    70893kB time= 1454.840 br=    10.4kbits/s avg_br=   399.2kbits/s type= ?
frame= 36368 q= -0.0 f_size=     67 s_size=    70893kB time= 1454.880 br=    13.4kbits/s avg_br=   399.2kbits/s type= ?
frame= 36368 q= -0.0 f_size=     56 s_size=    70893kB time= 1454.920 br=    11.2kbits/s avg_br=   399.2kbits/s type= ?

vorrei leggere l'ultima per farne il parser ed estrarne le informazioni salienti (e visualizzarle sul form)

il file lo apro per la lettura poco prima di iniziare la codifica:
Codice: [Seleziona]
Public Sub RunEncoder()
Dim Encoded As String[] 'la lista delle path di tutti i file dalla sorgente da codificare
Dim I As Integer
Dim OutputFileName As String

Dim StatFilePath As String

'provo a farmi un file con tutti i singoli comandi ffmpeg da lanciare   
'Dim hFile As File

Dim comando As String

  'col contributo di vuott:
  Creaso()

  Encoded = FileChooser_Sorgente.SelectedPaths

  'apre il file dello script per mettere il comando di codifica
  StatFilePath = FileChooser_Destinazione.Dir & "/MFRfile.txt"

  Do While Not ((bChiudo = True) Or (Encoded.count = 0)) 'fino a che non ho codificato tutti i file, oppure fino a quando non si preme "cancel"

    'codifica    'ffmpeg -i  "$f" -c:v libx265 -preset medium -crf 28 -c:a aac -b:a 128k -strict -2  "$( sed -e's/\.mpg/.mkv/g' <<< $f )"
    OutputFileName = File.BaseName(Encoded[0])
    OutputFileName = Replace(OutputFileName, " ", "_")
    OutputFileName = FileChooser_Destinazione.Dir & "/" & OutputFileName & ".mkv"

    'cancella il file delle statistiche se gia' esistente
    Try Kill StatFilePath

    'comando che in teoria dovrebbe andare bene con tanto di file delle stitistiche da spulciare per avere il progresso della codiifca
    comando = "ffmpeg -i " & Encoded[0] & " -c:v libx265 -preset medium -crf 28 -c:a aac -b:a 128k -strict -2 -vstats_file " & StatFilePath & " " & OutputFileName & " &"   'CON la & il comando va' in background

    Timer_Encode_status.Start
    hEncoderStatFile = Open StatFilePath For Read Create  'apro il file delle statistiche che poi leggero' nel timer

    Lancia_Comando(comando) 'in background con l'aggiunta della &

    'aspetta finche' il file e' codificato o il comando e' fallito
    Repeat
       Wait
    Until Timer_Encode_status.Enabled = False

    'se la codifica e' andata bene allora lo rimuovo
    Encoded.Remove(0)
  Loop
 
  ToggleButton_encode.Value = 0
 
End
se corri, morirai stanco (motto degli sniper)

Online vuott

  • Moderatore globale
  • Senatore Gambero
  • *****
  • Post: 11.284
  • Ne mors quidem nos iunget
    • Mostra profilo
Re:file.readline COME Leggere l'ultima riga?
« Risposta #3 il: 06 Ottobre 2016, 16:36:17 »
qualche volta il file viene letto prima di essere stato scritto ...

Vorrei cominciare dalle "periferie".... ma il Try non puoi sostituirlo così ?

Codice: [Seleziona]
If Exist(FileChooser_Destinazione.Dir & "/MFRfile.txt") Then
    testo = hEncoderStatFile.ReadLine(Null)
    if IsNull(testo) = False Then Label_statistiche.Text = Testo
  Endif

Anche in quest'altro caso:
Codice: [Seleziona]
'cancella il file delle statistiche se gia' esistente
    Try Kill StatFilePath
Non puoi sostituirlo con una condizione logica di controllo ?
Codice: [Seleziona]
If Exist(StatFilePath) Then Kill StatFilePath


... ma l'ultima riga e' quella con lo status corrente.

Posso fare un tail che voi sappiate?
vorrei leggere l'ultima per farne il parser ed estrarne le informazioni salienti ...
...cioè... tu vuoi di un normale , classico file di testo semplicemente leggere l'ultima riga ?
« Ultima modifica: 06 Ottobre 2016, 17:05:07 da vuott »
« Chiunque, non ricorrendo lo stato di necessità, nel proprio progetto Gambas fa uso delle istruzioni Shell o Exec, è punito con la sanzione pecuniaria da euro 20,00 a euro 60,00. »

Offline allegfede

  • Gran Maestro dei Gamberi
  • *****
  • Post: 738
    • Mostra profilo
Re:file.readline COME Leggere l'ultima riga?
« Risposta #4 il: 06 Ottobre 2016, 18:03:44 »
si l'ultima riga :D

un po' come nella shell fare:
 tail -n 1  MFRfile.txt

...secondo te' il try e' piu' o meno pesante per il sistema di una verifica con accesso al filesystem?

per me' una soluzione o l'altra e' indifferente, ma forse meno controlli=meno calcoli che levano cicli di elaborazione ad ffmpeg ...
se corri, morirai stanco (motto degli sniper)

Online vuott

  • Moderatore globale
  • Senatore Gambero
  • *****
  • Post: 11.284
  • Ne mors quidem nos iunget
    • Mostra profilo
Re:file.readline COME Leggere l'ultima riga?
« Risposta #5 il: 06 Ottobre 2016, 19:04:15 »
« Chiunque, non ricorrendo lo stato di necessità, nel proprio progetto Gambas fa uso delle istruzioni Shell o Exec, è punito con la sanzione pecuniaria da euro 20,00 a euro 60,00. »

Offline Gianluigi

  • Moderatore globale
  • Senatore Gambero
  • *****
  • Post: 4.157
  • Tonno verde
    • Mostra profilo
Re:file.readline COME Leggere l'ultima riga?
« Risposta #6 il: 06 Ottobre 2016, 20:08:33 »
si l'ultima riga :D

un po' come nella shell fare:
 tail -n 1  MFRfile.txt

...secondo te' il try e' piu' o meno pesante per il sistema di una verifica con accesso al filesystem?

per me' una soluzione o l'altra e' indifferente, ma forse meno controlli=meno calcoli che levano cicli di elaborazione ad ffmpeg ...
Come si vede  qui leggere un flile di testo è molto semplice.
Quindi per estrarre l'ultima riga dalla stringa si potrebbe usare Split e ottenere l'ultimo dato dell'array usando la proprietà Max.

È scritto di getto e probabilmente ci sono sistemi ancora più semplici.

Riguardo a Try oppure verificare con la funzione Exist penso che sia meglio semanticamente verificare prima, e probabilmente Try è più pesante.

 :ciao: :ciao:
nuoto in attesa del bacio di una principessa che mi trasformi in un gambero azzurro

Online vuott

  • Moderatore globale
  • Senatore Gambero
  • *****
  • Post: 11.284
  • Ne mors quidem nos iunget
    • Mostra profilo
Re:file.readline COME Leggere l'ultima riga?
« Risposta #7 il: 07 Ottobre 2016, 11:38:17 »
Gianluigi ha esaurientemente risposto sull'argomento, e tanto basterebbe; ma per mera curiosità mostriamo a coloro, che si affacciano or ora a Gambas, altre modalità di lettura dell'ultima riga di un file di testo.

Un file cosiddetto "di testo" ha la particolarità di essere costituito non solo da caratteri ASCII stampabili (ossia che non sono caratteri di controllo), ma anche di avere - al fine di consentire la visualizzazione delle righe l'una sotto l'altra - uno speciale carattere escape corrispondente al codice ASCII 0x0A (in Gambas: &h0A, o più semplicemente &0A), che è anche conosciuto ed utilizzato all'interno di una stringa come: \n.
Tale carattere escape, significante fine riga ed a capo, può dunque essere considerato un punto di riferimento fermo, certo, una sorta di faro per il programmatore all'interno del file di testo.
Quelle che per noi sono le classiche righe di un testo, nel file sono definite e distinte dal byte di valore 10 (0x0A).

Va evidenziato, inoltre, che il file di testo termina con carattere escape \n. Dunque l'ultimo byte di un file di testo ha sempre valore &0A.

Alla luce di quanto detto ben si comprende che i dati dell'ultima riga iniziano immediatamente dopo il penultimo byte di valore 0x0A (&0A),  posto alla fine dei byte costituenti la penultima riga, e termina con uguale carattere escape \n.
Pertanto sono questi due utlimi caratteri "faro" che noi dovremo tenere in dovuta considerazione e cercare. 

Detto ciò vediamo alcune modalità per individuare e raccogliere i byte dell'ultima riga di un file di testo.

1) con Line Input:
il comando Line Input legge i dati di un file di testo in blocchi definiti appunto dai byte di valore 0x0A (&0A in linguaggio Gambas). Ne consegue che l'ultima lettura corrisponde all'ultima riga !
Codice: [Seleziona]
Public Sub Main()

 Dim fl As File
 Dim s As String
 
   fl = Open "/percorso/del/file/di/testo" For Read

   While Not Eof(fl)
      Line Input #fl, s
' Se sono giunto alla fine del file, allora mostro la riga...che sarà ovviamente l'ultima:
      If Eof(fl) Then Print s
   Wend

End


2) con la proprietà .Lines di un file:
la proprietà .Lines, appartenente alle variabili di tipo File e Stream, si comporta sostanzialmente come la linea di comando Line Input precedentemente vista.
Pertanto potremo avere questo codice:
Codice: [Seleziona]
Public Sub Main()

 Dim fl As File
 Dim s As String
 
   fl = Open "/percorso/del/file/di/testo" For Read

   For Each s In fl.Lines
   Next

' L'ultima lettura contiene i dati dell'ultima riga del file di testo:
   Print s

End


3) con la funzione RInstr() ed altre funzioni stringa:
Come è noto, la funzione RInstr( ) di Gambas restituisce la posizione dell'ultimo carattere, indicato nel suo secondo paramentro, all'interno della stringa
Poiché sappiamo che l'ultima riga inizia immediamente dopo l'ultimo carattere escape \n del file di testo e termina con un altro carattere escape \n ...
Codice: [Seleziona]
Public Sub Main()

 Dim s As String
 Dim i As Integer
 
   s = File.Load("/percorso/del/file/di/testo")

' Elimino l'ultimo carattere escape \n dell'intero testo:
   s = Scan(s, "*\n")[0]

' ...ma potrei utilizzare anche questa riga:
''  s = Left(s, Len(s) - 1)

' Individuo la posizione dell'attuale ultimo carattere escape \n (che in origine era il penultimo):
   i = RInstr(s, "\n")
' Non mi resta altro che leggere i dati contenuti dall'ultimo dato a ritroso sino al dato
' posto immediatamente dopo il numero della posizione dell'ultimo carattere escape \n:
   s = Right(s, Len(s) - i)

   Print s

End


4) con le funzioni stringa InStr() e Mid()
Codice: [Seleziona]
Public Sub Main()

 Dim s As String
 Dim i, r As Integer
 Dim ii As New Integer[]

   s = File.Load("/percorso/del/file/di/testo")

   i = 1

' Carico tutte le occorrenze di \n:
   Do
     i = InStr(s, "\n", i)
     If i > 0 Then
       ii.Push(i)
       Inc i
       Inc r
     Endif
   Loop Until i = 0

   s = Mid(s, ii[ii.Max - 1] + 1, (ii[ii.Max] - ii[ii.Max - 1]) - 1)

   Print s

End

......e così via.
« Ultima modifica: 07 Ottobre 2016, 16:57:28 da vuott »
« Chiunque, non ricorrendo lo stato di necessità, nel proprio progetto Gambas fa uso delle istruzioni Shell o Exec, è punito con la sanzione pecuniaria da euro 20,00 a euro 60,00. »

Offline allegfede

  • Gran Maestro dei Gamberi
  • *****
  • Post: 738
    • Mostra profilo
Re:file.readline COME Leggere l'ultima riga?
« Risposta #8 il: 07 Ottobre 2016, 16:02:40 »
Come sempre molto esaurienti entrambi.

Peccato dover scorrere tutto il testo per estrarre solo l'ultima riga. Ma penso che per forza sia cosi', visto che comunque il file viene generato in modo progressivo, "appendendo" la nuova astringa DOPO l'ultima gia' scritta.

... inefficiente, ma penso che sia un limite dell'architettura dl filesystem :D
se corri, morirai stanco (motto degli sniper)

Offline Gianluigi

  • Moderatore globale
  • Senatore Gambero
  • *****
  • Post: 4.157
  • Tonno verde
    • Mostra profilo
Re:file.readline COME Leggere l'ultima riga?
« Risposta #9 il: 07 Ottobre 2016, 16:56:38 »
Si potrebbe aggiungere anche, che se desideriamo testare l'efficacia di uno spezzone di codice un metodo empirico ma sufficientemente efficace a patto di ripeterlo alcune volte è quello di usare la funzione Timer per cronometrarlo.
Ad esempio per conoscere se è più efficace l'uso di Try o la verifica con Exist potremmo fare:
Codice: [Seleziona]
' Gambas module file

Public Sub Main()

  Dim i As Integer
 
  For i = 1 To 10
    Print i; ")==================================="
    ConTry()
    ConExist()
  Next
 
End

Private Sub ConTry()
 
  Dim s As String
  Dim i As Integer
  Dim StartTime As Float
  Dim DiffTime As Float
 
  StartTime = Timer
  For i = 1 To 1000
    Try s = File.Load("~/inesistenteFile")
  Next
  DiffTime = Timer - StartTime
  Print "Con Try ", DiffTime * 1000; " msec"
 
End

Private Sub ConExist()
 
  Dim s As String
  Dim i As Integer
  Dim StartTime As Float
  Dim DiffTime As Float
 
  StartTime = Timer
  For i = 1 To 1000
    If Exist("~/inesistenteFile") Then
      s = File.Load("~/inesistenteFile")
    Endif
  Next
  DiffTime = Timer - StartTime
  Print "Con Exist ", DiffTime * 1000; " msec"
 
End
:ciao: :ciao:
nuoto in attesa del bacio di una principessa che mi trasformi in un gambero azzurro

Online vuott

  • Moderatore globale
  • Senatore Gambero
  • *****
  • Post: 11.284
  • Ne mors quidem nos iunget
    • Mostra profilo
Re:file.readline COME Leggere l'ultima riga?
« Risposta #10 il: 07 Ottobre 2016, 17:14:36 »
...circa la questione dell'uso del Try dico che tale funzione "ci prova ciecamente, ma non certifica".

...e ho detto tutto !



« Ultima modifica: 07 Ottobre 2016, 17:54:22 da vuott »
« Chiunque, non ricorrendo lo stato di necessità, nel proprio progetto Gambas fa uso delle istruzioni Shell o Exec, è punito con la sanzione pecuniaria da euro 20,00 a euro 60,00. »