C# przesuwanie strumienia

0

Mam problem z wydobyciem fragmentu strumienia do innego strumienia.

Otóż w programie uzyskałem strumień, którego początkowy fragment to nagłówki html, a dalej znajduje się treść pliku jpg (klasyczna odpowiedź serwera na pobranie pliku).

Niestety, kiedy odczytam potrzebne mi nagłówki, a następnie strumień przekażę do konstruktora obiektu Bitmap, to program wywala wyjątek. Po sprawdzeniu zauważyłem, że gdy tworzę nowego streamReadera na częściowo odczytanym strumieniu to znowu czyta nagłówki. Czy da się jakoś utworzyć kopię strumienia zaczynającą się w punkcie, gdzie StreamReader skończył czytać??

0

Jaki wyjątek wywala i jak podajesz ten strumień? Spróbuj pokombinować z właściwością Position.

0

Wywala:

System.ArgumentException: Parametr jest nieprawidłowy.
at System.Drawing.Bitmap..ctor
at MoneyBot.PtrBot.MainClass.DecodeConfirmImage in d:\projekty\C#\MoneyBot\MoneyBot.PtrBot\MainClass.cs:line 387
at MoneyBot.PtrBot.MainClass.DecodePreHTML in d:\projekty\C#\MoneyBot\MoneyBot.PtrBot\MainClass.cs:line 358
at MoneyBot.PtrBot.MainClass.UsePTC in d:\projekty\C#\MoneyBot\MoneyBot.PtrBot\MainClass.cs:line 450
at MoneyBot.PtrBot.MainClass.UseSomething in d:\projekty\C#\MoneyBot\MoneyBot.PtrBot\MainClass.cs:line 335
at MoneyBot.PtrBot.MainClass.Run in d:\projekty\C#\MoneyBot\MoneyBot.PtrBot\MainClass.cs:line 118
at System.Threading.ThreadHelper.ThreadStart_Context
at System.Threading.ExecutionContext.Run
at System.Threading.ThreadHelper.ThreadStart

A program działa mniej więcej tak:

Klasa połączenia:


                private void TransformHeaders(StreamReader sr){
                	string s = "";
                	string header = "";
                	do{
                		s = sr.ReadLine();
                		header+=s+"\n";
                	}while(s!="");
                	TransformHeaders(header);
                }
                
 
                
                private void TransformHeaders(string header){
               		Console.WriteLine(header);
               		foreach(Match m in Regex.Matches(header, "Set-Cookie: ([^=]*)=([^;]*)")){
                		SetCookie(m.Groups[1].Value, m.Groups[2].Value);
                	}
                }
                
                public StreamReader SendGet(string addres){
                	
               		if(addres.Contains(host)){
                		
                		socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                		socket.Connect(host, 80);
                		
                		addres = addres.Substring(addres.IndexOf(host)+host.Length);
                		
                		NetworkStream ns = new NetworkStream(socket, true);
                		StreamWriter sw = new StreamWriter(ns);
                		StreamReader sr = new StreamReader(ns);
                		
                		sw.WriteLine("GET "+addres+" HTTP/1.1");
                		sw.WriteLine("Host: "+host);
                		sw.WriteLine("User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-EN; rv:1.8.0.1) Gecko/20060313 Debian/1.5.dfsg+1.5.0.1-4 Firefox/1.5.0.1");
                		sw.WriteLine("Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5");
                		sw.WriteLine("Accept-Language: en-us;q=0.7,en;q=0.3");
                		sw.WriteLine("Accept-Encoding: gzip,deflate");
                		sw.WriteLine("Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7");
                		sw.WriteLine("Connection: keep-alive");
                		if(HasCookies) sw.WriteLine(GetCookieHeaderString());
                		sw.WriteLine();
                		
                		
                		sw.Flush();
                		
                		TransformHeaders(sr);
                		
                		return sr;
                	}
                	return null;
                }

I funkcja z błedem:

System.Drawing.Bitmap i01 = new System.Drawing.Bitmap(conn.SendGet(url).BaseStream);
				
0

Bo strumien zapisuje sie jako utf8 (domysl bo nie ma wszytskiego), moze wytestuj BinaryWriter/Reader.

Dla uproszenia masz tez w C# klasy: WebClient, WebRequest.

Jak podajesz naglowki to musisz byc tez na nie przygotowany (np. gzip)

0

Znalazłem coś dziwnego. Strumień jednak przesuwa się prawidłowo, ale mimo, iż Zwrotny nagłówek ContentLenght ma wartość ok 2000, to funkcja

conn.SendGet(url).ReadToEnd().Lenght

Zwraca wartość ok 1500, tak jakby strumień był niedoczytywany. Może w tym problem?

bo nie ma wszytskiego

Napisałem wszystko co ważne, nie dopisałem tylko konstruktora, który jedynie przydziela wartość host np. na "www.google.com" i funkcji obsługi cookies, bo działają one prawidłowo.

0

conn.SendGet(url).ReadToEnd().Lenght

tak ale to utf8 .... a nie binarny ciag. dwa rzone znaki moga dac jeden znak UTF8
Jak wpakowalem tam BinaryReadera bylo OK. (wystraczy nawet popatrzec, ze pierwsze bajty jpeg'a sa nie takie w tym przykladzie).

0
hubert_nnn napisał(a)

Napisałem wszystko co ważne, nie dopisałem tylko konstruktora, który jedynie przydziela wartość host np. na "www.google.com" i funkcji obsługi cookies, bo działają one prawidłowo.

tak ale jak chce przetestowac kod, to musze wykomentowac ... MWE > minimal working example

0

A po co ci takie czyste pisanie po socketach? Są odpowiednie klasy do tego i to w dostatecznym stopniu pozwalające na konfigurację.

Net.HttpWebRequest httpWebRequest = (Net.HttpWebRequest)Net.HttpWebRequest.Create(
    @"http://esamultimedia.esa.int/images/EarthObservation/MER_FR__0PNPDE20090822_0830.JPG");

httpWebRequest.UserAgent = @"User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-EN; rv:1.8.0.1) Gecko/20060313 Debian/1.5.dfsg+1.5.0.1-4 Firefox/1.5.0.1";
httpWebRequest.Accept = @"text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5";
httpWebRequest.Headers.Add(Net.HttpRequestHeader.AcceptLanguage, "en-us;q=0.7,en;q=0.3");
httpWebRequest.Headers.Add(Net.HttpRequestHeader.AcceptEncoding, "gzip,deflate");
httpWebRequest.AutomaticDecompression = Net.DecompressionMethods.GZip | Net.DecompressionMethods.Deflate;

Image image;
using (Net.HttpWebResponse httpWebResponse = (Net.HttpWebResponse)httpWebRequest.GetResponse())
{
    IO.Stream httpWebResponseStream = httpWebResponse.GetResponseStream();
    image = Image.FromStream(httpWebResponseStream);
}
0

Wiem, że są, ale miałem ich dosyć. Od tygodnia męczyłem się, żeby identyfikator sesji nie zmieniał się przy każdym wywołaniu. I nic nie działało. Zwyczajnie nawet, jeśli uzyskany phpsessid dodałem do ciastek tuż przed wysłaniem pakietu, to i tak zwracany był nowy kod. Problem w tym, że strona, z której pobieram obrazek wymaga, abym był zalogowany.

Reichel, jak to zrobiłeś, że program działa z tymi BinaryReaderami?

0

jeszcze moze byc tak

StreamReader sr = new StreamReader(ns, Encoding.GetEncoding("ISO-8859-1"));

zapisuje do pliku OK, nie wiem czemu nie chce czytac ze strumienia - nie wglebialem sie.

0
reichel napisał(a)

zapisuje do pliku OK

Mi coś takiego nie zapisuje do pliku prawidłowo:

System.IO.File.WriteAllText("aaa.jpg", SendGet(url).ReadToEnd());

0

Udało mi sie zapisać plik w ten sposób:

StreamReader sr = SendGet(url);
System.IO.File.WriteAllText("aaa.jpg", sr.ReadToEnd(), System.Text.Encoding.GetEncoding("ISO-8859-1"));

Problem w tym, że po sprawdzeniu pliku narzędziem hex program gubi wyższe bajty np. nagłówek jpg:

FFD8 FFE0 0010 4A46 4946 0001 0100 0001
zastępuje
3F3F 3F3F 0010 4A46 4946 0001 0100 0001

i tak w całym zapisanym pliku jest pełno takich znaków 3F3F
Jak to rozwiązać? Bo to chyba właśnie tu jest problem.

0

Jak napisalem albo readery do Latin1 - to to ISO (ja zapisywalem przez FileStream z ustawionym Latin1 jak podalem i zapisal OK), albo BinaryReader

ogolnie tak dziala (ale nie jest to czyste rozwiazanie)


  StreamReader sr = new StreamReader(ns, Encoding.GetEncoding("ISO-8859-1"));
 ....

 public static byte[] StrToByteArray(string str)
        {
            Encoding encoding = Encoding.GetEncoding("ISO-8859-1");
            return encoding.GetBytes(str);
        }
//rozbite aby pokazac kroki
           MemoryStream ms = new MemoryStream();

           string rr = sr.ReadToEnd();

            Byte[] bb = StrToByteArray(rr);

            ms.Write(bb, 0, bb.Length);

            System.Drawing.Bitmap i01 = new System.Drawing.Bitmap(ms);

            ms.Close();

0

Problem nie zniknął. Plik zapisuje się, zle część bajtów jest zdegradowana. Na rysunku pokazana jest struktura pliku popranego przez program (po lewej) i przez przeglądarkę (po prawej). Ramką oznaczyłem przykładowy fragment z problemem.

http://img21.imageshack.us/img21/8902/problemzhj.jpg

Pliki nie są całkiem identyczne, bo z każdym razem program generuje nowy, ale problem powinno byc wyraźnie widać (te ciagi znaków zapytania o kodzie 3F3F)

0

Podaj swoj minimalny kod - wyciete wszytsko co z ciastkami - moze maly projekt
tak aby dalo sie skompilowac Od razu.

0

Trochę tego dużo, ale nie chciałem niczego ważnego pominąć:


using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Text.RegularExpressions;
using System.Collections.Generic;

namespace Tester
{
	/// <summary>
	/// Description of Polaczenie.
	/// </summary>
	public class Polaczenie
    {
				string host;
                
                Socket socket;
                
                Dictionary<string, string> cookies = new Dictionary<string, string>();
                	
                public Polaczenie(string host)
                {
                      this.host = host;
                       
                }
                
                
                public string phpsessid{
                	get{
                		string s = "";
                		cookies.TryGetValue("PHPSESSID", out s);
                		return s;
                	}
                }
                
               	private bool loggedIn = false;
                
                private void SetCookie(string name, string value){
                	if(cookies.ContainsKey(name)) cookies.Remove(name);
                	if(value!="deleted"){
                		cookies.Add(name, value);
                	}
                	if(name == "autousername") loggedIn = true;
                }
                
                private bool HasCookies{
                	get{
                		return cookies.Count>0;
                	}
                }
                
                private string GetCookieHeaderString(){
                	StringBuilder sb = new StringBuilder("Cookie: ");
                	foreach(KeyValuePair<string, string> cookie in cookies){
                		sb.Append(cookie.Key+"="+cookie.Value+"; ");
                	}
                	return sb.ToString();
                }
                
                private void TransformHeaders(StreamReader sr){
                	string s = "";
                	string header = "";
                	do{
                		s = sr.ReadLine();
                		header+=s+"\n";
                	}while(s!="");
                	TransformHeaders(header);
                }
                
                private void TransformHeaders(string header){
               		Console.WriteLine(header);
               		foreach(Match m in Regex.Matches(header, "Set-Cookie: ([^=]*)=([^;]*)")){
                		SetCookie(m.Groups[1].Value, m.Groups[2].Value);
                	}
                }
                
                public bool IsLoggedIn(){
                	return loggedIn;
                }
                
                public StreamReader SendGet(string addres){
                	
               		if(addres.Contains(host)){
                		
                		socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                		socket.Connect(host, 80);
                		
                		addres = addres.Substring(addres.IndexOf(host)+host.Length);
                		
                		NetworkStream ns = new NetworkStream(socket, true);
                		StreamWriter sw = new StreamWriter(ns);
                		StreamReader sr = new StreamReader(ns);
                		BinaryReader br = new BinaryReader(ns);
                		
                		sw.WriteLine("GET "+addres+" HTTP/1.1");
                		sw.WriteLine("Host: "+host);
                		sw.WriteLine("User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-EN; rv:1.8.0.1) Gecko/20060313 Debian/1.5.dfsg+1.5.0.1-4 Firefox/1.5.0.1");
                		sw.WriteLine("Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5");
                		sw.WriteLine("Accept-Language: en-us;q=0.7,en;q=0.3");
                		sw.WriteLine("Accept-Encoding: gzip,deflate");
                		sw.WriteLine("Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7");
                		sw.WriteLine("Connection: keep-alive");
                		if(HasCookies) sw.WriteLine(GetCookieHeaderString());
                		sw.WriteLine();
                		
                		sw.Flush();
                		
                		Console.WriteLine("AAA");
                		Console.WriteLine(br.ReadString());

                		TransformHeaders(sr);
                		
                		Console.WriteLine("SESJA: "+phpsessid);
                		
                		return sr;
                	}
                	return null;
                }
		}
	
	
	class Program
	{
		public static void Main(string[] args)
		{
			
			Polaczenie conn = new Polaczenie("cda.pl");
			StreamReader sr = conn.SendGet("http://www.cda.pl/images/logo-mniejsze.jpg");
			
			
			System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(sr.BaseStream);
			
			
			Console.Write("Press any key to continue . . . ");
			Console.ReadKey(true);
		}
	}
}

Acha, zapomniałem o usingach

0

Moja propozycja na szybko byla by taka (lepiej jednak zastanow sie cze HttpRequest nie bedzie lepsze, tam sie tez da ustawic sesje etc. i dziala na pewno - z doswiadczenia!)

namespace Tester
{
        /// <summary>
        /// Description of Polaczenie.
        /// </summary>

public class Polaczenie
    {
        string host;

        Socket socket;

        Dictionary<string, string> cookies = new Dictionary<string, string>();

        public Polaczenie(string host)
        {
            this.host = host;

        }


        public string phpsessid
        {
            get
            {
                string s = "";
                cookies.TryGetValue("PHPSESSID", out s);
                return s;
            }
        }

        private bool loggedIn = false;

        private void SetCookie(string name, string value)
        {
            if (cookies.ContainsKey(name)) cookies.Remove(name);
            if (value != "deleted")
            {
                cookies.Add(name, value);
            }
            if (name == "autousername") loggedIn = true;
        }

        private bool HasCookies
        {
            get
            {
                return cookies.Count > 0;
            }
        }

        private string GetCookieHeaderString()
        {
            StringBuilder sb = new StringBuilder("Cookie: ");
            foreach (KeyValuePair<string, string> cookie in cookies)
            {
                sb.Append(cookie.Key + "=" + cookie.Value + "; ");
            }
            return sb.ToString();
        }

        private void TransformHeaders(StreamReader sr)
        {
            string s = "";
            string header = "";
            do
            {
                s = sr.ReadLine();
                header += s + "\n";
            } while (s != "");
            TransformHeaders(header);
        }

        private void TransformHeaders(string header)
        {
            Console.WriteLine(header);
            foreach (Match m in Regex.Matches(header, "Set-Cookie: ([^=]*)=([^;]*)"))
            {
                SetCookie(m.Groups[1].Value, m.Groups[2].Value);
            }
        }

        public bool IsLoggedIn()
        {
            return loggedIn;
        }

        public static byte[] StrToByteArray(string str)
        {
            Encoding encoding = Encoding.GetEncoding("ISO-8859-1");
            return encoding.GetBytes(str);
        }

        public MemoryStream SendGet(string addres)
        {

            if (addres.Contains(host))
            {

                socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                socket.Connect(host, 80);

                addres = addres.Substring(addres.IndexOf(host) + host.Length);

                NetworkStream ns = new NetworkStream(socket, true);
                StreamWriter sw = new StreamWriter(ns);
                StreamReader sr = new StreamReader(ns, Encoding.GetEncoding("ISO-8859-1"));
                BinaryReader br = new BinaryReader(ns);

                sw.WriteLine("GET " + addres + " HTTP/1.1");
                sw.WriteLine("Host: " + host);
                sw.WriteLine("User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-EN; rv:1.8.0.1) Gecko/20060313 Debian/1.5.dfsg+1.5.0.1-4 Firefox/1.5.0.1");
                sw.WriteLine("Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5");
                sw.WriteLine("Accept-Language: en-us;q=0.7,en;q=0.3");
                sw.WriteLine("Accept-Encoding: gzip,deflate");
                sw.WriteLine("Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7");
                sw.WriteLine("Connection: keep-alive");
                if (HasCookies) sw.WriteLine(GetCookieHeaderString());
                sw.WriteLine();

                sw.Flush();

                Console.WriteLine("AAA");
                Console.WriteLine(br.ReadString());

                TransformHeaders(sr);

                Console.WriteLine("SESJA: " + phpsessid);



                //mozna tu pokombinowac aby bylo ladniej
                MemoryStream ms = new MemoryStream();                               
                Byte[] data = StrToByteArray(sr.ReadToEnd());

                ms.Write(data, 0, data.Length);                

                return ms;
            }
            return null;
        }
    }



 class Program
        {
                public static void Main(string[] args)
                {
                        
                        Polaczenie conn = new Polaczenie("cda.pl");
                        MemoryStream sr = conn.SendGet("http://www.cda.pl/images/logo-mniejsze.jpg");
                        
                        
                        System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(sr);

                        sr.Close();
                        
                        
                        Console.Write("Press any key to continue . . . ");
                        Console.ReadKey(true);
                }
        }

}

1 użytkowników online, w tym zalogowanych: 0, gości: 1