Reading and parsing text file exception-C# - winforms

I am parsing big text files and it's working fine for some time but after few minutes it give me exception (An unhandled exception of type 'System.UnauthorizedAccessException' occurred in System.Core.dll
Additional information: Access to the path is denied.)
I get exception on below mention line.
accessor = MemoryMapped.CreateViewAccessor(offset, length, MemoryMappedFileAccess.Read);
Below is my function
public static void CityStateZipAndZip4(string FilePath,long offset,long length,string spName)
{
try
{
long indexBreak = offset;
string fileName = Path.GetFileName(FilePath);
if (fileName.Contains(".txt"))
fileName = fileName.Replace(".txt", "");
System.IO.FileStream file = new System.IO.FileStream(#FilePath, FileMode.Open,FileAccess.Read, FileShare.Read );
Int64 b = file.Length;
MemoryMappedFile MemoryMapped = MemoryMappedFile.CreateFromFile(file, fileName, b, MemoryMappedFileAccess.Read, null, HandleInheritability.Inheritable, false);
using (MemoryMapped)
{
//long offset = 182; // 256 megabytes
//long length = 364; // 512 megabytes
MemoryMappedViewAccessor accessor = MemoryMapped.CreateViewAccessor(offset, length, MemoryMappedFileAccess.Read);
byte byteValue;
int index = 0;
int count = 0;
StringBuilder message = new StringBuilder();
do
{
if (indexBreak == index)
{
count = count + 1;
accessor.Dispose();
string NewRecord = message.ToString();
offset = offset + indexBreak;
length = length + indexBreak;
if (NewRecord.IndexOf("'") != -1)
{ NewRecord = NewRecord.Replace("'", "''"); }
// string Sql = "insert into " + DBTableName + " (ID, DataString) values( " + count + ",'" + NewRecord + "')";
string Code = "";
if (spName == AppConfig.sp_CityStateZip)
{
Code = NewRecord.Trim().Substring(0, 1);
}
InsertUpdateAndDeleteDB(spName, NewRecord.Trim (), Code);
accessor = MemoryMapped.CreateViewAccessor(offset, length, MemoryMappedFileAccess.Read);
message = new StringBuilder();
index = 0;
//break;
}
byteValue = accessor.ReadByte(index);
if (byteValue != 0)
{
char asciiChar = (char)byteValue;
message.Append(asciiChar);
}
index++;
} while (byteValue != 0);
}
MemoryMapped.Dispose();
}
catch (FileNotFoundException)
{
Console.WriteLine("Memory-mapped file does not exist. Run Process A first.");
}
}

Somewhere deep in resource processing code we have something like this:
try {
// Try loading some strings here.
} catch {
// Oops, could not load strings, try another way.
}
Exception is thrown and handled already, it would never show up in your application. The only way to see it is to attach debugger and observe this message.
As you could see from the code, it has nothing to do with your problem. The real problem here is what debugger shows you something you should not see.
Run the solution without debugging mode and it works fine.

This exception means that your program does not get Read access to the file from Windows.
Have you made sure that this file is not locked when your program tries to read it ?
For example, it could be a file that your own program is currently using.
If not, try to run your program as an Administrator and see if it makes a difference.

Related

Failed to send Http request based on MFC

I'm new to HTTP and MFC. I suppose to upload a binary file to a given URL, by sending PUT request. I'm sure the requesting URL and the header are well formed and the file works well, because I tried them by Postman then get a SUCCESS returned.
But when I try to do this by the following MFC code, it always returns a 403 error. Please help me.
bool UploadFile(LPCTSTR strUrl, LPCTSTR filenameFullpath, CString header)
{
BOOL bResult = FALSE;
DWORD dwType = 0;
CString strServer;
CString strObject;
INTERNET_PORT wPort = 0;
DWORD dwFileLength = 0;
BYTE * pFileBuff = NULL;
CHttpConnection * pHC = NULL;
CHttpFile * pHF = NULL;
CInternetSession cis;
bResult = AfxParseURL(strUrl, dwType, strServer, strObject, wPort);
if (!bResult)
return FALSE;
CFile file;
try
{
// Read the file
if (!file.Open(filenameFullpath, CFile::shareDenyNone | CFile::modeRead))
return FALSE;
dwFileLength = file.GetLength();
if (dwFileLength <= 0)
return FALSE;
pFileBuff = new BYTE[dwFileLength];
memset(pFileBuff, 0, sizeof(BYTE) * dwFileLength);
file.Read(pFileBuff, dwFileLength);
// Set up internet connection
const int nTimeOut = 5000;
cis.SetOption(INTERNET_OPTION_CONNECT_TIMEOUT, nTimeOut);
cis.SetOption(INTERNET_OPTION_CONNECT_RETRIES, 2); // Retry once if failed
pHC = cis.GetHttpConnection(strServer, dwType == AFX_INET_SERVICE_HTTP ? NORMAL_CONNECT : SECURE_CONNECT, wPort); // Get a HTTP connection
pHF = pHC->OpenRequest(CHttpConnection::HTTP_VERB_PUT, strObject);//strObject
pHF->AddRequestHeaders(header , HTTP_ADDREQ_FLAG_ADD_IF_NEW);
// I set the header separately instead of passing it as the first parameter of the next call.
// If I don't do so, another error occurs
if (!pHF->SendRequest(NULL, 0, pFileBuff, dwFileLength))
{
delete[]pFileBuff;
pFileBuff = NULL;
pHF->Close();
pHC->Close();
cis.Close();
return FALSE;
}
DWORD dwStateCode = 0;
pHF->QueryInfoStatusCode(dwStateCode);
if (dwStateCode == HTTP_STATUS_OK)
bResult = TRUE;
}
catch (CInternetException * pEx)
{
char sz[256] = "";
pEx->GetErrorMessage(sz, 25);
CString str;
str.Format("InternetException occur!\r\n%s", sz);
AfxMessageBox(str);
}
delete[]pFileBuff;
pFileBuff = NULL;
file.Close();
pHF->Close();
pHC->Close();
cis.Close();
return bResult;
}
And the calling of this function is just something like this:
CHttpClient hc;
hc.UploadFile(csUrl, "E:\\blah blah blah\\blah.tma", csUploadHeader);
while csUrl and csUploadHeader are well formed CString;
I got it! I should give pHF the header items (the key-value pairs) one by one, by calling the AddRequestHeaders() method several times, instead of wrapping and passing them together to pHF.
Then the following codes works very well:
CString sHeader1, sHeader2, sHeader3;
sHeader1.Format(_T("%s : %s"), sKey1, sValue1); // sKey_, sValue_ are strings
sHeader2.Format(_T("%s : %s"), sKey2, sValue2);
sHeader3.Format(_T("%s : %s"), sKey3, sValue3);
pHF->AddRequestHeaders(sHeader1, HTTP_ADDREQ_FLAG_ADD_IF_NEW); // Keep the second paeramter as these
pHF->AddRequestHeaders(sHeader2, HTTP_ADDREQ_FLAG_COALESCE);
pHF->AddRequestHeaders(sHeader3, HTTP_ADDREQ_FLAG_COALESCE);
And a very important notification: the string we pass to AddRequestHeaders() should not have the quotation("") around either the key or the value. In other words, string like "MyKey":"MyValue" have to be modified as MyKey:MyValue before giving to AddRequestHeaders();

How to add subMsg to msg repeated using Nanopb?

I'm simply trying to add one message to another message (up to 60 times times)
My .proto file looks as follows;
syntax = "proto3";
message FeatureFile {
string fileName= 2;
string Id= 3;
repeated Feature features = 1;
}
message Feature {
int32 version = 1;
int32 epochTime = 2;
int32 noOfObs= 3;
int32 frequency = 4;
}
I have tried to make a callback function to add repeated data, but cannot make it work.
bool encode_string(pb_ostream_t* stream, const pb_field_t* field, void* const* arg)
{
const char* str = (const char*)(*arg);
if (!pb_encode_tag_for_field(stream, field))
return false;
return pb_encode_string(stream, (uint8_t*)str, strlen(str));
}
bool encode_repeatedMsg(pb_ostream_t* stream, const pb_field_t* field, void* const* arg)
{
const char* obj = (const char*)(*arg);
int i;
for (i = 0; i < 60; i++)
{
if (!pb_encode_tag_for_field(stream, field))
return false;
if (!pb_encode_submessage(stream, Feature_fields, *arg))
return false;
}
return true;
}
int main()
{
FeatureFile featurefile = FeatureFile_init_zero;
Feature feature = Feature_init_zero;
featurefile.fileName.arg = "092536.csv";
featurefile.fileName.funcs.encode = &encode_string;
featurefile.Id.arg = "";
featurefile.Id.funcs.encode = &encode_string;
feature.version = 1;
feature.epochTime = 12566232;
feature.noOfObs = 260;
feature.frequency = 200;
featurefile.features.funcs.encode = &encode_repeatedMsg;
I thought I could call the repeated encoding like the last line of code shows, but I doesn't allow me.
The callback itself is supposed to add 60 of the same messages (feature) to the the featurefile.
Can anyone help me here?
I myself have never used the callbacks in nanopb. I do have been using the .options file to statically allocate the desired array size. Your case this might be a bit much as your require 60 messages but this is how you do it:
You create a file with the same name as your .proto file but give it the extension .options. You place it in the same folder as your .proto file. In that file you mention there repeated variable name and assign it a size:
# XXXX.options
FeatureFile.features max_count:16
More information on the nanopb options can be found here.

JavaMail don't read MimeMultipart emails

if (contentType.contains("multipart")) {
// content may contain attachments
Multipart multiPart = (Multipart) message.getContent();
numberOfParts = multiPart.getCount();
for (int partCount = 0; partCount < numberOfParts; partCount++) {
BodyPart part = multiPart.getBodyPart(partCount);
String disposition = part.getDisposition();
InputStream inputStream = null;
if (disposition == null)
{
MimeBodyPart mbp = (MimeBodyPart) multiPart.getBodyPart(partCount);
if (mbp.getContent() instanceof MimeMultipart){
MimeMultipart mmp = (MimeMultipart) mbp.getContent();
messageContent = mmp.getBodyPart(0).getContent().toString();
//System.out.println("bodyContent " + bodyContent);
}
else
{
messageContent = multiPart.getBodyPart(partCount).getContent().toString();
}
}
else if (Part.ATTACHMENT.equalsIgnoreCase(part.getDisposition())) {
// this part is attachment
String fileName = part.getFileName();
attachFiles += fileName + ", ";
//part.saveFile(saveDirectory + File.separator + fileName);
}else if (Part.INLINE.equalsIgnoreCase(part.getDisposition())) {
// this part is attachment
String fileName = part.getFileName();
attachFiles += fileName + ", ";
// mbp.saveFile(saveDirectory + File.separator + fileName);
}
else {
// this part may be the message content
messageContent = part.getContent().toString();
}
}
if (attachFiles.length() > 1) {
attachFiles = attachFiles.substring(0, attachFiles.length() - 2);
}
} else if (contentType.contains("text/plain") || contentType.contains("text/html")) {
Object content = message.getContent();
if (content != null) {messageContent = content.toString(); }
}
And now this type of message text / plain, text / html gets well. The problem is the email multipart / related when the message has attachments and content is HTML, then gets some news and some not. I noticed that it is dependent on this line:
messageContent = mmp.getBodyPart (0). getContent (). toString ();
If instead of "0" is "partCount" gets all but one particular, if instead of "0" is "1" gets me this one specific and does not charge others. numberOfParts this one particular message is "3" and the other "2". I have no idea what is wrong, maybe wrong parameters are passed?
I'm not really sure what problem you're trying to solve, but just in case this JavaMail FAQ entry might be helpful.
multipart/mixed and multipart/related are very similar in that they have one main part and a bunch of other parts usually thought of as "attachments". Sometimes the disposition will tell you that it's an attachment, and sometimes it won't. Some mailers aren't very consistent in their use of disposition.
One of the unusual cases is multipart/alternative, but it doesn't sound like that's the problem you're running in to.

Silverlight Socket Constantly Returns With Empty Buffer

I am using Silverlight to interact with a proxy application that I have developed but, without the proxy sending a message to the Silverlight application, it executes the receive completed handler with an empty buffer ('\0's). Is there something I'm doing wrong? It is causing a major memory leak.
this._rawBuffer = new Byte[this.BUFFER_SIZE];
SocketAsyncEventArgs receiveArgs = new SocketAsyncEventArgs();
receiveArgs.SetBuffer(_rawBuffer, 0, _rawBuffer.Length);
receiveArgs.Completed += new EventHandler<SocketAsyncEventArgs>(ReceiveComplete);
this._client.ReceiveAsync(receiveArgs);
if (args.SocketError == SocketError.Success && args.LastOperation == SocketAsyncOperation.Receive)
{
// Read the current bytes from the stream buffer
int bytesRecieved = this._client.ReceiveBufferSize;
// If there are bytes to process else the connection is lost
if (bytesRecieved > 0)
{
try
{
//Find out what we just received
string messagePart = UTF8Encoding.UTF8.GetString(_rawBuffer, 0, _rawBuffer.GetLength(0));
//Take out any trailing empty characters from the message
messagePart = messagePart.Replace('\0'.ToString(), "");
//Concatenate our current message with any leftovers from previous receipts
string fullMessage = _theRest + messagePart;
int seperator;
//While the index of the seperator (LINE_END defined & initiated as private member)
while ((seperator = fullMessage.IndexOf((char)Messages.MessageSeperator.Terminator)) > 0)
{
//Pull out the first message available (up to the seperator index
string message = fullMessage.Substring(0, seperator);
//Queue up our new message
_messageQueue.Enqueue(message);
//Take out our line end character
fullMessage = fullMessage.Remove(0, seperator + 1);
}
//Save whatever was NOT a full message to the private variable used to store the rest
_theRest = fullMessage;
//Empty the queue of messages if there are any
while (this._messageQueue.Count > 0)
{
...
}
}
catch (Exception e)
{
throw e;
}
// Wait for a new message
if (this._isClosing != true)
Receive();
}
}
Thanks in advance.
I assume the second block of code is your ReceiveComplete handler. If so, you should be looking at the SocketAsyncEventArgs.BytesTransferred property to get the count of the bytes received.

Problem in retrieving the ini file through web page

I am using an .ini file to store some values and retrieve values from it using the iniparser.
When I give (hardcode) the query and retrive the value through the command line, I am able to retrive the ini file and do some operation.
But when I pass the query through http, then I am getting an error (file not found), i.e., the ini file couldn't be loaded.
Command line :
int main(void)
{
printf("Content-type: text/html; charset=utf-8\n\n");
char* data = "/cgi-bin/set.cgi?pname=x&value=700&url=http://IP/home.html";
//perform some operation
}
Through http:
.html
function SetValue(id)
{
var val;
var URL = window.location.href;
if(id =="set")
{
document.location = "/cgi-bin/set.cgi?pname="+rwparams+"&value="+val+"&url="+URL;
}
}
.c
int * Value(char* pname)
{
dictionary * ini ;
char *key1 = NULL;
char *key2 =NULL;
int i =0;
int val;
ini = iniparser_load("file.ini");
if(ini != NULL)
{
//key for fetching the value
key1 = (char*)malloc(sizeof(char)*50);
if(key1 != NULL)
{
strcpy(key1,"ValueList:");
key2 = (char*)malloc(sizeof(char)*50);
if(key2 != NULL)
{
strcpy(key2,pname);
strcat(key1,key2);
val = iniparser_getint(ini, key1, -1);
if(-1 == val || 0 > val)
{
return 0;
}
}
else
{
//error
free(key1);
return;
}
}
else
{
printf("ERROR : Memory Allocation Failure ");
return;
}
}
else
{
printf("ERROR : .ini File Missing");
return;
}
iniparser_freedict(ini);
free(key1);
free(key2);
return (int *)val;
}
void get_Value(char* pname,char* value)
{
int result =0;
result = Value(pname);
printf("Result : %d",result);
}
int main(void)
{
printf("Content-type: text/html; charset=utf-8\n\n");
char* data = getenv("QUERY_STRING");
//char* data = "/cgi-bin/set.cgi?pname=x&value=700&url=http://10.50.25.40/home.html";
//Parse to get the values seperately as parameter name, parameter value, url
//Calling get_Value method to set the value
get_Value(final_para,final_val);
}
*
file.ini
*
[ValueList]
x = 100;
y = 70;
When the request is sent through html page, I am always getting .ini file missing. If directly the request is sent from C file them it works fine.
How to resolve this?
Perhaps you have a problem with encoding of the URL parameters? You can't just pass any arbitrary string through a URL - there are some characters that must be encoded. Read this page about URL encoding.
Showing the value of the data string in your C program could be of great help with solving your problem.
Update:
There could be a difference as to where your program executes when called by the web server or directly by you. Are you sure it's being executed with the same "current directory". Chances are it's different, and thus when you attempt to open the ini file you fail. Try to print out the current directory (i.e. using the getcwd function) and compare both cases.

Resources