Zápis (přepis) do zvoleného místa v souboru   zodpovězená otázka

VB.NET, I/O operace

Zdravím,

Přecházím do Visual Basicu 2008 Professional Edition SP1.

Potřebuji přepisovat posloupnost několika znaků,

od zvoleného místa v existujícím souboru.

v .NET CompactFramework 1.0, 2.0

Celková velikost souboru zůstává stejná.

Třída BinaryWriter se zdá být nepoužitelná,

překvapivě při zápisu vkládá jeden znak navíc (01 hexa)

(viz níže)

Dělám snad něco špatně?

Nebo jak jinak na to?

Please help! :-)

Takto jsem dopadl s BinaryWriter

==================================

původní obsah souboru: "12345"

hexadecimálně: (31 32 33 34 35)

když se snažím přepsat číslo "3", písmenem "C"

s pomocí BinaryWriter

dopadne to takto

Obsah souboru: "12C5"

hexadecimálně: (31 32 01 43 35)

Pro úplnost, potřebuji aby to bylo

Obsah souboru: "12C45" :-)

==========================

také jsem zkoušel

využít FileStream

je to sice už funkční ale mám pocit

že to půjde ještě elegantněji

viz více dole

Zde je úplný kod s BinaryWriter

Option Explicit On 
Option Strict On 

Imports Microsoft.VisualBasic 
Imports System 
Imports System.IO 

Public Class Form1 

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load 


Dim fileName As String = "D:\ ...\Soubor.txt" 
Dim textByteChr As String = "C" 


Dim binWriter As New BinaryWriter( _ 
File.Open(fileName, FileMode.Open, FileAccess.Write), _ 
System.Text.Encoding.GetEncoding(1250)) 

binWriter.Seek(2, SeekOrigin.Begin) 
binWriter.Write(textByteChr) 

binWriter.Close() 

End Sub 

End Class 

více úspěšnější jsem byl takto ale ..,

Dim textByteChr As String = "67" '"C"=43hex, "C"=67dec 

Dim fileStream As FileStream = _ 
New FileStream(fileName, FileMode.Open) 

fileStream.Seek(2, SeekOrigin.Begin) 

fileStream.WriteByte(CByte(textByteChr)) 

fileStream.Close() 

ale připadá mi to neefektivní

převádět řetězec na ASCII hodnoty

a také jsem nenašel jak nastavit typ znakové sady.

Předpokládám, že to jde i jinak a efektivněji.

Díky moc za jakékoliv náměty.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

To je pěkná blbost. Nejdřív si načtěte soubor do Textboxu a tam si s ním už můžete dělat cokoliv.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

To má být nějaký špatný vtip?

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Jedná se o mobilní zařízení, kde nesmí dojít ke ztrátě již zapsaných dat. Proto data (celý soubor) neupravuji v RAM, ale přímo zapisuji na paměťové médium. Možná diskutabilní, ale zadavatelem požadované. Z toho nemohu uhnout.

I tak díky za názor.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Problém bude asi v kódování toho souboru. Ujistěte se, že daný soubor je skutečně v kódování Windows-1250 a ne v Unicode.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

to: Ondřej Linhart

Soubor je vytvořen v Poznámkovém bloku na Win XP CZ SP3

při volbě Uložit jako.., je nastaveno kodování ANSI

(soubor obsahuje pouze těch 5 znaků, a ani není odřádkován)

To by snad

jako rychlá kontrola mohlo stačit.

Shodneme se?

Rozhodně díky za podmět,:-)

kódovani souboru jsem před tím nekontroloval.

Taky mám pocit, že by to s tím kódováním mohlo souviset,

Ale jak?

Znamená v Unicode, ten znak navíc "01 Hex" něco konkrétního?

Přitom je zajímavé, že při zápisu

- s pomocí "FileStream" je to OK

ačkoliv kodovani neurčuji

- s pomocí "BinaryWriter" je to KO

ať je kódování zadáno či nikoliv.

Zajímalo by mě, také zda se i vám ostatním

konkrétní řešení s "BinaryWriter" uvedené výše, především ve VB .NET chová stejně podivně.

Můžete to prosím někdo vyzkoušet

a napsat jak to dopadlo, či v jaké verzi VB?

dík předem.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

To, co dělá BinaryWriter je očekávatelné a správné chování, chybu máte v kódu Vy. V první ukázce metodě Write předáváte proměnnou typu String, tím pádem tam zapíše řetězec (pro to používá nějaký svůj vlastní způsob, musí se tam uložit asi i délka řetězce nebo něco takového, ta 01 hex je možná značka, že řetězec končí; navíc ten řetězec je z principu Unicode, zapisuje se to asi v UTF-8, protože je to základní znak, zabere jen 1 bajt, ten druhý bude asi značka - nevím, ale takhle bych to viděl).

Je nutné si uvědomit, že pokud pracujete s FileStreamem nebo s BinaryWriterem, neřešíte žádné kódování ani nic podobného, pracujete na úrovni bajtů (až na to zapisování Stringu přes BinaryWriter, ale to je jenom speciální způsob, jak uložit na úrovni bajtů a zase přečíst řetězec).

Vy chcete pravděpodobně pracovat s bajty, takže klidně stačí používat obyčejný FileStream a jeho metody Seek, ReadByte a WriteByte. Každý znak ve Windows-1250 má svoji hodnotu, zjistit ji pro daný znak můžete přes nějakou funkci ze System.Text.Encoding.Default.něco.

nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět

Díky moc za odpověď.

Přecházím z VB6 a teprve si zvykám na odlišný přístup .NETu.

Jasně, už došlo, :-) není třeba řešit kodování, protože místo vlastnho znaku zadávám přímo jeho kód.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Už vím! :-),

u BinaryWriter, metody Write (String),

se nejdříve zapisuje délka zapisovaného řetězce a pak následně zadaný řetězec.

Tím je objasněna výše zmiňovaná záhadná 01hex, je to délka zapsaného řetězce.

z dokumentace:

Write(String)

- Writes a length-prefixed string

to this stream in the current encoding of the BinaryWriter, and advances the current position of the stream in accordance

with the encoding used and the specific characters being written to the stream.

Remarks

A length-prefixed string represents the string length by prefixing to the string a single byte or word that contains the

length of that string. This method first writes the length of the string as a four-byte unsigned integer, and then writes

that many characters to the stream. This method writes a length-prefixed string to this stream using the BinaryWriter

instance's current Encoding.

Zdroj:

BinaryWriter.Write Method (String)

http://msdn.microsoft.com/en-us/library/...

případně také

String Definitions

http://msdn.microsoft.com/en-us/library/...

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Zde přikládám pro druhé, funkční řešení s pomocí BinaryWriter a jeho metody Write(Char)

(děkuji tímto za pomoc panu Tomáši Hercegovi)

Dim fileName As String = "D:\Soubor.txt" 
Dim textByteChr As Char = "A"c
Dim posun As Integer

Dim FS As New FileStream(fileName, FileMode.Open)

Dim BW As New BinaryWriter(FS,System.Text.Encoding.ASCII)

	posun = 0
	BW.Seek(posun, SeekOrigin.Begin)

	
        'na začátku souboru,
        ' se přepíše první znak(byte), znakem "A"

	BW.Write(textByteChr)

BW.Close()
FS.Close()

Využil jsem možnosti zadat do typu CHAR přímo znak

Dim textByteChr As Char = "A"c

(viz písmeno c na konci)

za pomocí "Forced Literal Types"

zdroj

http://msdn.microsoft.com/en-us/library/...

http://msdn.microsoft.com/en-us/library/...

nebo je tu nějaký důvod proč to nepoužívat?

je otázkou je, co je rychlejší, zda výše uvedené

nebo příkazy navíc, kde si nejdříve ze znaku určím jeho kód a ten následně vložím do proměnné textByteChr.

co na to zkušenější?

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Řešení s "a"c je naprosto v pořádku a bude nepatrně rychlejší, ovšem ten rozdíl nebude nijak dramatický.

Obávám se, že ale nebude fungovat, pokud bude kód znaku větší než 127, nejsem si tím jistý. Otázkou je, jestli to potřebujete.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Re: Kodování

ano, stačí mi

zapisovat znaky z oblasti 0 až 127 (dolní polovina ASCII),

pak nemusím řešit kodování,

v této části je stejné v Unicode i v ASCII

The first 128 code points (0–127) of Unicode correspond to the letters and symbols on a standard U.S. keyboard

These first 128 code points are the same as those the ASCII character set defines.

http://msdn.microsoft.com/en-us/library/...

Díky všem za příspěvky,

Každá reakce mi pomohla zamyslet se nad problémem z jiné strany.

Je fajn, že tu ta možnost je, takže především díky provozovatelům webu.

nahlásit spamnahlásit spam 0 odpovědětodpovědět
                       
Nadpis:
Antispam: Komu se občas házejí perly?
Příspěvek bude publikován pod identitou   anonym.
  • Administrátoři si vyhrazují právo komentáře upravovat či mazat bez udání důvodu.
    Mazány budou zejména komentáře obsahující vulgarity nebo porušující pravidla publikování.
  • Pokud nejste zaregistrováni, Vaše IP adresa bude zveřejněna. Pokud s tímto nesouhlasíte, příspěvek neodesílejte.

přihlásit pomocí externího účtu

přihlásit pomocí jména a hesla

Uživatel:  
Heslo:  

zapomenuté heslo

 

založit nový uživatelský účet

zaregistrujte se

 
zavřít

Nahlásit spam

Opravdu chcete tento příspěvek nahlásit pro porušování pravidel fóra?

Nahlásit Zrušit

Chyba

zavřít

feedback