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?
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':
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:
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
qualche volta il file viene letto prima di essere stato scritto ...
Vorrei cominciare dalle "periferie".... ma il Try non puoi sostituirlo così ?
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:
'cancella il file delle statistiche se gia' esistente
Try Kill StatFilePath
Non puoi sostituirlo con una condizione logica di controllo ?
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 ?
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 !
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:
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 ...
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()
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.
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:
' 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: