Консультация № 179772
24.08.2010, 12:02
43.65 руб.
0 24 1
Здравствуйте, уважаемые эксперты!
Я пишу в Visual Studio 2008, MFC.
Помогите пожалуйста, как мне загрузить txt файл из интернета (например http://mysite.ru/123.txt) в переменную CString?
Нужен по возможности самый быстрый способ, чтобы можно было загружать несколько раз в секунду.

Обсуждение

Неизвестный
24.08.2010, 12:57
общий
А обязательно MFC? Вот вариант под .Net. Если пойдет, можно оформить ответом. Полезный код - 4 строчки из последнего метода. А если очень хочется, их можно и в 1 упихать :)

Код:
#pragma once


namespace CPP_WinForms {

using namespace System;
using namespace System::ComponentModel;
using namespace System::Collections;
using namespace System::Windows::Forms;
using namespace System::Data;
using namespace System::Drawing;
using namespace System::Net;
using namespace System::IO;

/// <summary>
/// Summary for Form1
///
/// WARNING: If you change the name of this class, you will need to change the
/// 'Resource File Name' property for the managed resource compiler tool
/// associated with all .resx files this class depends on. Otherwise,
/// the designers will not be able to interact properly with localized
/// resources associated with this form.
/// </summary>
public ref class Form1 : public System::Windows::Forms::Form
{
public:
Form1(void)
{
InitializeComponent();
//
//TODO: Add the constructor code here
//
}

protected:
/// <summary>
/// Clean up any resources being used.
/// </summary>
~Form1()
{
if (components)
{
delete components;
}
}
private: System::Windows::Forms::TextBox^ textBox1;
protected:
private: System::Windows::Forms::Button^ button1;

private:
/// <summary>
/// Required designer variable.
/// </summary>
System::ComponentModel::Container ^components;

#pragma region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
void InitializeComponent(void)
{
this->textBox1 = (gcnew System::Windows::Forms::TextBox());
this->button1 = (gcnew System::Windows::Forms::Button());
this->SuspendLayout();
//
// textBox1
//
this->textBox1->Anchor = static_cast<System::Windows::Forms::AnchorStyles>((((System::Windows::Forms::AnchorStyles::Top | System::Windows::Forms::AnchorStyles::Bottom)
| System::Windows::Forms::AnchorStyles::Left)
| System::Windows::Forms::AnchorStyles::Right));
this->textBox1->Location = System::Drawing::Point(12, 12);
this->textBox1->Multiline = true;
this->textBox1->Name = L"textBox1";
this->textBox1->ScrollBars = System::Windows::Forms::ScrollBars::Both;
this->textBox1->Size = System::Drawing::Size(611, 473);
this->textBox1->TabIndex = 0;
//
// button1
//
this->button1->Anchor = static_cast<System::Windows::Forms::AnchorStyles>((System::Windows::Forms::AnchorStyles::Bottom | System::Windows::Forms::AnchorStyles::Left));
this->button1->Location = System::Drawing::Point(12, 491);
this->button1->Name = L"button1";
this->button1->Size = System::Drawing::Size(75, 23);
this->button1->TabIndex = 1;
this->button1->Text = L"Request";
this->button1->UseVisualStyleBackColor = true;
this->button1->Click += gcnew System::EventHandler(this, &Form1::button1_Click);
//
// Form1
//
this->AutoScaleDimensions = System::Drawing::SizeF(6, 13);
this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font;
this->ClientSize = System::Drawing::Size(635, 517);
this->Controls->Add(this->button1);
this->Controls->Add(this->textBox1);
this->Name = L"Form1";
this->Text = L"Form1";
this->ResumeLayout(false);
this->PerformLayout();

}
#pragma endregion
private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e) {

WebRequest^ Request = WebRequest::Create("http://lleo.aha.ru/na/");
WebResponse^ Response = Request->GetResponse();
StreamReader^ SR = gcnew StreamReader(Response->GetResponseStream(), System::Text::Encoding::GetEncoding("Windows-1251"));
String^ S = SR->ReadToEnd();

textBox1->Text=S;
}
};
}
Неизвестный
24.08.2010, 13:02
общий
Но несколько раз в секунду может быть и опасно. Тут куче пакетов приходится много раз туда-сюда пробегать. Если задержки большие (сервер далеко), может больше 2-3 раз в секунду и не успевать, даже при высокой скорости подключения. FTP и HTTP в таких сценариях очень плохо себя ведут.
Неизвестный
24.08.2010, 13:15
общий
Evgenijm, 2-3 раза в секунду даже хватит.

А как этот код переписать под MFC? Где описаны WebRequest,WebResponse ?
Неизвестный
24.08.2010, 13:25
общий
Я MFC вообще не пользовался. Так что совсем не вкурсе, к сожалению. Мне проще Вас на .Net перетащитьЕсли надо обязательно работать с MFC и не получится там легко получить эту штуку, то можно сделать смешанное приложение. Глупо, конечно, ради нескольких строчек, но возможно. Тогда останется лишь преобразовывать CString->String->CString. Или вообще просто полученные байты передавать.

Не уверен, что в MFC есть что-то типа WebRequest. Эта библиотека мне показалась довольно низкоуровневой.
Неизвестный
24.08.2010, 13:34
общий
Мне проще Вас на .Net перетащить

Это нужно в visual studio создавать CLR приложение Windows Forms?
Когда я его создаю, не могу редактировать вкладку "Form1.h [конструктор]". Вот скрин: http://img682.imageshack.us/img682/8479/52383731.jpg.
Остальные файлы .h, .cpp могу редактировать, компилируется нормально.
Собственно, из-за этого я пишу на mfc
Неизвестный
24.08.2010, 13:48
общий
Это означает, что произошла ошибка при создании окна либо в коде, либо в контроле, который на форму положили. За это я тоже C++.Net очень не люблю. Чтобы получить досту к коду, откройте форму в эксплорере не двойным щелчком, а правой кнопкой и там "View Code". Сторонние компоненты на форму не добавляли? Они могут ошибки выдавать и конструктор вообще не запускается тогда. Еще надо попробовать скомпилировать. Может тогда вменяемую ошибку покажет, а не это "что-то где-то".

Еще проще - перейти на C#. Там не будет никаких MFC, глючных дизайнеров и ужасных gcnew и ^

После С он очень простой. И очень похож на Яву.
Неизвестный
24.08.2010, 14:10
общий
Evgenijm,
Компилируется нормально, ошибок нет. Когда я установил студию, так сразу было. Конструктор не открывается и всё тут

А если на C# создаю Windows Forms, то вылезает ошибка "Запрошенный доступ к реестру запрещен".
( винда vista sp2, студию запускаю от администратора)
Неизвестный
24.08.2010, 14:37
общий
Что-то там не так с установкой. У меня под Вистой проблем вообще не было. Аккаунт был тоже пользовательским с возможностью админа. Какая версия студии? И не бета ли случайно? Или до этого бета не стояла? У них была прошлым летом проблема с бетами. Мне пришлось зимой переставлять всю систему: не обновлялось ничего из-за внутренних ошибок фреймворка.
Неизвестный
24.08.2010, 21:58
общий
Не бета. Профессионал.
Попробую windows 7 поставить.
Неизвестный
25.08.2010, 23:23
общий
Evgenijm,
Все, поставил C#.
Как мне этот код изменить под него, чтобы работал?
Неизвестный
26.08.2010, 12:19
общий
Код абсолютно тотже, только синтаксис гораздо проще.
На форму кинуть текстбокс и кнопку. Текстбокс сделать многострочным и с ползунками. У кнопки докинг сделать внизу, а у текстбокса - заполнение. Вот этот обработчик события для кнопки все сделает:
Код:
private void button1_Click(object sender, EventArgs e)
{
WebRequest Request = WebRequest.Create("http://lleo.aha.ru/na/");
WebResponse Response = Request.GetResponse();
StreamReader SR = new StreamReader(Response.GetResponseStream(), System.Text.Encoding.GetEncoding("Windows-1251"));
String S = SR->ReadToEnd();

textBox1->Text=S;
}


Вы вообще что с полученым текстом делать собираетесь?
Неизвестный
26.08.2010, 12:30
общий
Ошибка "Не удалось найти имя типа или пространства имен "WebRequest""

Вообще я хочу управлять программой через интернет. Нажимаю кнопку на сайте, в файл на хостинге записывается определенная команда, программа считывает ее и выполняет.
Неизвестный
26.08.2010, 12:40
общий
Сверху надо еще using System.Net; добавить. Или нажать в коде на слово WebRequest и выбрать в смарттаге его добавление.
Неизвестный
26.08.2010, 12:44
общий
Так может получиться довольно опасная штукаВыполнение команд тогда тоже можно сделать в этой же программе
Неизвестный
26.08.2010, 12:47
общий
спасибо) оформите ответом?
Неизвестный
26.08.2010, 12:48
общий
почему опасная?) то что часто шлет запросы ?
Неизвестный
26.08.2010, 13:07
общий
Если выполняются опасные команды, то можно огрести хорошо :)

Кстати, файл загрузится, но с сервера он не удалится и не изменится.
Неизвестный
26.08.2010, 13:11
общий
да, я знаю. для этого программа отправляет запрос что команда обработана и файл нужно очистить.
кстати, как лучше его отправить? наиболее оптимально и быстро? что-то типа "mysite.ru/index.php?value=0". ответ получать не нужно

з.ы. это не троян)
Неизвестный
26.08.2010, 13:57
общий
это ответ
Здравствуйте, Иванов Роман Витальевич.

Вот, как и обговорили в минифоруме, пример кода на C#. Здесь 2 функции:
GetTextFile возвращает весь текст в одной строке. Быстро, но не подходит для больших файлов и оставляет переносы строк без изменения. Юниксовые переносы в текстбоксе не обрабатываются.
GetTextStrings читает файл построчно. При этом юниксовые переносы распознаются тоже. Для обработки файла обычно используется такой код.
Как видно, у Экслера есть оба типа переносов.

Для примера добавьте на форму 2 кнопки и текстбокс. Щелкните 2 раза по обеим кнопкам, а потом замените код формы на нижеследующий. Установка свойств в конструкторе только для примера, это все легко делается в редакторе формы. Первая кнопка загружает файл целиком, а вторая - построчно.

Код:
using System;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.IO;
using System.Collections.Generic;


namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
button1.Dock = DockStyle.Bottom;
button2.Dock = DockStyle.Bottom;

textBox1.Multiline = true;
textBox1.Dock = DockStyle.Fill;
textBox1.WordWrap = false;
textBox1.ScrollBars = ScrollBars.Both;
}

private void button1_Click(object sender, EventArgs e)
{
textBox1.Text = GetTextFile("http://exler.ru", Encoding.GetEncoding("Windows-1251"));
}

//Возвращаем текст целиком
private static String GetTextFile(String Link, Encoding Encoding)
{
WebRequest Request = WebRequest.Create(Link);
WebResponse Response = Request.GetResponse();
StreamReader SR = new StreamReader(Response.GetResponseStream(), Encoding);
return SR.ReadToEnd();
}

private void button2_Click(object sender, EventArgs e)
{
List<String> Strings = GetTextStrings("http://exler.ru", Encoding.GetEncoding("Windows-1251"));
textBox1.Lines = Strings.ToArray();
}

//Возвращаем список строк
private static List<String> GetTextStrings(String Link, Encoding Encoding)
{
WebRequest Request = WebRequest.Create(Link);
WebResponse Response = Request.GetResponse();
StreamReader SR = new StreamReader(Response.GetResponseStream(), Encoding);

List<String> Strings = new List<String>();
String S;
while ((S = SR.ReadLine()) != null)
Strings.Add(S);

return Strings;
}
}
}
5
Неизвестный
26.08.2010, 14:00
общий
Думаю, что точно также. Только поток уже брать не нужно. Попробуйте так:

WebRequest Request = WebRequest.Create("http://mysite.ru/index.php?value=0");
WebResponse Response = Request.GetResponse();
Неизвестный
26.08.2010, 20:31
общий
Первые 2 прохода нормально обрабатываются, а на третьей всегда зависает программа.

private void button1_Click(object sender, EventArgs e)
{
WebRequest Request = WebRequest.Create("http://mysite.ru/cmd.txt");
WebResponse Response = Request.GetResponse();
StreamReader SR = new StreamReader(Response.GetResponseStream(), System.Text.Encoding.GetEncoding("Windows-1251"));
String S = SR->ReadToEnd();
textBox1->Text=S;

WebRequest Request2 = WebRequest.Create(http://mysite.ru/index.php?value=0);
WebResponse Response2 = Request2.GetResponse();

}

Если убрать это:
WebRequest Request2 = WebRequest.Create(http://mysite.ru/index.php?value=0);
WebResponse Response2 = Request2.GetResponse();
то программа нормально работает.

В чем может быть дело?
Неизвестный
27.08.2010, 13:17
общий
Думаю, что сайт не отвечает. Как с ним надо работать, я еще не разбирался. Возможно, надо все-таки читать поток из ответа или закрывать его сразу. Если у сервера остается много "висячих" соединений, он перестает создавать новые. Еще можно у запроса таймаут поставить. Но скорее всего, проблема получается у сервера. Надо разбираться, что ему не нравится.

Попробуйте для начала поставить
Response2.GetResponseStream().Close();
Неизвестный
16.09.2010, 12:57
общий
На C++ код никто так и не написал? (me нашёл письмо в куче непрочитанных месяц назад...)
Неизвестный
16.09.2010, 13:09
общий
/me порылся

Если актуально, то в MFC есть класс CInternetSession:

Цитата: msdn
Establish a connection. Create a CInternetSession to establish the basis of an Internet client application.

Open a URL. Establish a connection.
Call CInternetSession::OpenURL.
The OpenURL function returns a read-only resource object.

Read URL data. Open the URL.
Call CInternetFile::Read.
Форма ответа