[ komplikator @ 03.08.2018. 10:59 ] @
Pozdrav svima,

nekad sam bio Delphi programer i znao riješiti ovakvu stvar, no sad to trebam napraviti u powershellu, naravno jedino pomoću .net objekata.

Imam jedan (zapravo brdo) datoteka od po 250MB koje su zapravo streamovi u kojima su upakirane slike (nadzornih kamera). Trebam prolaziti kroz binarni stream i dijelove streama odijeljene start i stop delimiterom exportati u file. Tu stvar imam već odrađenu u pythonu tj. primjer koji je netko na Internetu odradio u pythonu i tu skriptu sada pozivam iz powershella. Cilj mi je sve odraditi u powershellu.

Ovo je primjer u pythonu:

Code:

start = 0
  end = 0

  with open(file_input, 'rb') as f:
    f.seek(0, 2)
    num_bytes = f.tell()

    print ("File Size: %.2f MB" % float(num_bytes / 1024 / 1024))
    print()
    i = 0
    status = "No files written"
    t = tqdm(total=num_bytes, unit='B', unit_scale=True, unit_divisor=1024, desc="Progress")

    mm = mmap.mmap(f.fileno(), 0, access=mmap.ACCESS_READ)

    while 1:

      f.seek(end)

      t.set_description(status)

      start = mm.find(b'\xFF\xD8', end)
      if start == -1:
        break

      end = mm.find(b'\xFF\xD9', start)

      if (picture % args.every == 0):

        filename = args.prefix + "-" + str(count) + ".jpg"

        filename_output = output_dir.joinpath(Path(filename).name)
        file_output = open(filename_output, 'wb')
        f.seek(start)
        jpeg_data = f.read(end - start)
        file_output.write(jpeg_data)
        file_output.close()
        status = "File " + filename + " written"
        count += 1
      picture += 1
      t.update(end - start)

  t.update(num_bytes - t.n)
  t.close()
  f.closed



Ja sam za sada došao do ovdje:

Code:

$path = "C:\_playground\test\hiv00000.pic"
$fsReader =  New-Object System.IO.BinaryReader ([System.IO.File]::Open($path, [System.IO.FileMode]::Open, [System.IO.FileAccess]::Read, [System.IO.FileShare]::ReadWrite))
$lPos = $fsFile.Seek(0, [System.IO.SeekOrigin]::Begin)


Ima li netko volje prepisati ovo u .net kod? Moje ideje koje pale u Delphiju u .net-u. ne prolaze, no svakako bilo bi dobro da se zbog brzine i optimizacije koristi file stream ili neki cachirani stream i dio streama između start i stop indexa samo kopira u novi filestream.

Najsporija metoda bila bi proći kroz cijeli stream i pročitati sve start i stop markere od početka do kraja jer ni u jednoj .net stream ili reader klasi ne vidim neku .Find metodu za traženje binarnog patterna od trenutne pozicije u streamu pa prema EOF-u. tj. kraju streama/buffera.

Bio bi zahvalan na pomoći i sugestiji kako to izvesti.
Unaprijed, hvala!
[ komplikator @ 17.08.2018. 12:50 ] @
S obzirom da nitko ne odgovara evo odgovora... No stvar je spora i ima puno mjesta za optimizaciju.

Code:

cls

$path = "C:\_playground\test\hiv00000.pic"

$startTag = 0xFFD8
$endTag   = 0xFFD9
$fsReader =  New-Object System.IO.BinaryReader ([System.IO.File]::Open($path, [System.IO.FileMode]::Open, [System.IO.FileAccess]::Read, [System.IO.FileShare]::ReadWrite))

$lPos = $fsReader.BaseStream.Seek(0, [System.IO.SeekOrigin]::Begin)


$fileData = $fsReader.ReadBytes($fsReader.BaseStream.Length)

$brStart=-1
$brStop=0
$dataLen = $fileData.Length
$dataLen = 10 * 1MB
$start = 0
$stop = 0

write-host ("File name: " + $path)
write-host ("Data size in MB: " + $DataLen/1MB)

for ( $i = 0; $i -lt $dataLen-1; $i++)

    {

        #$IPer = $i / $dataLen * 100

        #Write-Progress -Activity "Searching stream "  -CurrentOperation "Index: $I " -Status ($IPer.ToString('N2') + "% Complete:")  -PercentComplete $IPer 


        if (($fileData[$i] -eq 0xFF) -and ($fileData[$i+1] -eq 0xD8)) 
            {
                $brStart++
                $Start = $i
                write-host "*******************************************"
                write-host ("mark at: $i  " + [String]::Format("{0:x}",$fileData[$i]) + [String]::Format("{0:x}",$fileData[$i+1]))
            }


        if (($fileData[$i] -eq 0xFF) -and ($fileData[$i+1] -eq 0xD9)) 
            {
                $brStop++
                $stop = $i
                write-host ("mark at: $i  " + [String]::Format("{0:x}",$fileData[$i]) + [String]::Format("{0:x}",$fileData[$i+1]))
                write-host ("Size of part: "+ ($stop-$start))
                Write-Host "Reader len"  $fsReader.BaseStream.Length


                if ($start -ge 0) 
                    {

                        $fsWriter =  New-Object System.IO.BinaryWriter ([System.IO.File]::Open("C:\_playground\test\" + "IMG"+($brStart.ToString("000000")) +".JPG", [System.IO.FileMode]::OpenOrCreate))
                        $spReader = $fsReader.BaseStream.Seek($start,[System.IO.SeekOrigin]::Begin)
                        $fsReader.BaseStream.CopyTo($fsWriter.BaseStream, ($stop - $start))
                        $fsWriter.BaseStream.SetLength(($stop - $start))
                        $fsWriter.Close();
                    }
            }



    }

write-host "-------------------------------------------"
write-host "Number of files : "  $brStart