|
Extensions aren't trustworthy, nothing guarantees the file is in the format it says it's on. The developer himself might have changed the extension to better suit his application, as evidenced by the shitload of formats that are just XML files, compressed or not, with a different extension (like SVG).
As for the first few bytes, many formats have common prefixes (there's 2 or 3 exemples on the list you linked, but there's more), some of them don't even require the prefix to be present and others (like SVG) are encoded as text that can have yet another prefix (BOM).
It's sad, but we can't trust the format markers when dealing with multiple formats.
|
|
|
|
|
Because the actual internal error being thrown is an OutOfMemoryException. That has been my experience, especially when working with LEADTools libraries and images with OCR software.
Edit: I have seen this similar thing happen before, and for some reason the image "may" be corrupted and thus causes a memory issue. Then the developer just returns a crap message saying not a valid image format. But in reality, the software kept reading the bytes until it ran out of memory.
|
|
|
|
|
Because a useful name for the exception was out-of-the-memory of the developer.
Oh sanctissimi Wilhelmus, Theodorus, et Fredericus!
|
|
|
|
|
The GDI classes seem to be simply a .net facade\interface to the actual underlying code and that code only seems to return generic error messages that are of no help at all. Any issue that happens with GDI simply returns "A generic error occured" even if the error has a specific cause. So I'm going to guess that the reason better exceptions are not thrown is simply because the .net part of the equation doesn't know what the problem is as GDI only bubbles up weird or vague error messages.
|
|
|
|
|
The return exception is known: out of memory. I have a lot of experience with OCR and images, etc. and this is a common error in underlying C++ libraries when reading the bytes of an image, etc.
So, the error is factual and known: out of memory error, usually attributed to an corrupt file format.
The user friendly message is still mostly accurate here. It should say something like "your image file format is incorrect or corrupted as the software was unable to process it without error." -- or something like that.
|
|
|
|
|
In a moment of clarity, I recalled the answer: they are applying the Maunder Minimum. 8)
|
|
|
|
|
Chris Maunder wrote: and using something like UnsupportedFormatException is too hard?
Just be glad its not the usual, "Error occurred", Good luck figuring it out.
Common sense is admitting there is cause and effect and that you can exert some control over what you understand.
|
|
|
|
|
Looks like it's the same reason why renaming an EXE to COM and trying to load it generates an "Out of memory" error: Implementation details leaking to the surface.
|
|
|
|
|
I mean, not really? COM files have a size limit because they behave different from EXE files (or rather, EXE files behave different, since COM is the original). When you try to load a COM file that exceeds this limit you're really running out of memory, before the code can even start to be executed.
Could they read the file size and predict that? they couldn't (or just didn't, hard to say with stuff this old) when COM files where actually being used, so the current included loaders also don't. You don't really want to mess with those kinds of legacy systems, specially when they are useless for current developments and the alternative doesn't share the concerns.
COM file - Wikipedia
|
|
|
|
|
Don't care, I always use
catch(Exception e){..} That always works
|
|
|
|
|
I was watching a very good intro to Functional programming on PluralSight (Functional Programming with C# | Pluralsight[^]) and the author / presenter created the following method (mine has altered var names).
public static class Helper{
public static T Tee<T>(
T @inVal,
Action<T> act){
act(@inVal);
return @inVal;
}
}
Now you can call that method like the following:
Helper.Tee("test", Console.WriteLine);
Helper.Tee(3.238, Console.WriteLine);
Helper.Tee (new {garbage="super"},Console.WriteLine);
Here's the output:
test
3.238
{ garbage = super }
It's loosely based on the following idea (why it's named Tee): tee (command) - Wikipedia[^]
Just thought it was an interesting example and it made me think differently about things.
After all these years of OOP I'm beginning to see the real value in the Functional paradigm*.
*Obviously the included sample is not a huge example of Functional programming in and of itself.
|
|
|
|
|
How is that any different from calling Console.WriteLine("test"); etc.?
It's just more code to call Console.WriteLine and you aren't chaining anything or using the Tee output
Even worse, an Action<T> assumes a side-effect because it doesn't return a value.
Or is Tee used to "hide" this side-effect?
If I read the wiki page I'd suspect Tee does the Console.WriteLine and you can pass in a File.WriteText or something similar, but even then I fail to see how Tee is helping you. You could just as well call both methods.
|
|
|
|
|
I like your questions because I'm learning the concepts and determining how these things are important too. And I can tell by your questions that you have more functional experience than I do.
Here's an example that may make more sense -- it's like a before and after test.
Helper.Tee(Helper.Tee(" _ before after _ ", Console.WriteLine)
.ToUpper().Trim()
.Substring(8,6),
Console.WriteLine);
That results in an output like the following:
_ before after _
AFTER
Because the Tee method returns the value methods can be chained just like the normal string methods and so you can see the BEFORE version of your string and then the AFTER version.
I don't know if that is helpful either, but it's interesting.
This was a very small portion of an example showing how to create fluent APIs.
|
|
|
|
|
This definitely looks like a case for an extension method[^].
" _ before after _ "
.Tee(Console.WriteLine)
.ToUpper().Trim()
.Substring(8, 6)
.Tee(Console.WriteLine);
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
Ah, yes, that would be even better. Makes far more sense that way.
|
|
|
|
|
That was interesting to me so I altered the Tee method to make it an extension method.
Simply add the _this_ to the first param T and your code works now.
public static class Helper{
public static T Tee<T>(
this T @inVal,
Action<T> act){
act(@inVal);
return @inVal;
}
}
" _ before after _ "
.Tee(Console.WriteLine)
.ToUpper().Trim()
.Substring(8,6)
.Tee(Console.WriteLine);
|
|
|
|
|
Like Richard, I was thinking of an extension method.
What you have there is pretty hard to read, took me a while to figure out what it does (due to the nested Tee, which is not a very helpful name either).
I'm all for chaining though, that's what LINQ does too (which is pretty functional).
Applying functional principles (but remembering C# is not a functional language) really helped me write cleaner and more succinct code.
Although not everyone agrees with me, some people prefer their foreach loops and can't read lambda's
One thing I've learned, and taken to heart, a function has input and predictable output (no side-effects or state!).
At some point you're going to have state and output, of course, but that's reserved for special classes.
To give an example (from the top of my head, ignore bad practices such as public fields):
public class BadClass
{
public string s;
public void BadClass(string s)
{
this.s = s;
}
public void DoubleString()
{
s = s + s;
}
}
var bc = new BadClass("Hello");
bs.DoubleString();
Console.WriteLine(bc.s);
public class GoodClass
{
public void DoubleString(string s)
{
return s + s;
}
}
var gc = new GoodClass();
var s = gc.DoubleString("Hello");
Console.WriteLine(s); It's a bit contrived, but you'd be amazed at how often I've seen the BadClass implementation (equivalent) of this.
People just love their state and side effects.
But then again, I've worked on old VB applications with old VB programmers...
As coincidence would have it Packt offers a free Functional C#[^] eBook today, may be interesting (haven't read it myself).
|
|
|
|
|
Hi Sander,
Evidently PackT changes which book is free every day, so that one is no longer free.
cheers, Bill
«... thank the gods that they have made you superior to those events which they have not placed within your own control, rendered you accountable for that only which is within you own control For what, then, have they made you responsible? For that which is alone in your own power—a right use of things as they appear.» Discourses of Epictetus Book I:12
|
|
|
|
|
Yeah, that's why I said "today" yesterday
|
|
|
|
|
I just ask that, if you've no state, make the damn method static.
The amount of times I had to rewrite stuff because people fumbled around with instances of a stateless object and later added state to that object, breaking half the code depending on execution order is uncanny.
It's fine to be an instance method if you class has an immutable state. At least nobody would come and remove a const or readonly from a field without the knowledge that it would break everything... I hope...
|
|
|
|
|
Sander Rossel wrote: How is that any different from calling Console.WriteLine("test"); etc.?
It's just more code to call Console.WriteLine and you aren't chaining anything or using the Tee output
Using a Hello World example would be so much more useful!
CQ de W5ALT
Walt Fair, Jr., P. E.
Comport Computing
Specializing in Technical Engineering Software
|
|
|
|
|
What a weird, but interesting, idea.
I think a better example than
Helper.Tee("test", Console.WriteLine);
could be
string result = Helper.Tee("test", Console.WriteLine).ToUpper();
That shows the "T " character of that function more clearly: since it returns the input parameter, you can chain a few functions.
Oh sanctissimi Wilhelmus, Theodorus, et Fredericus!
|
|
|
|
|
You are exactly correct about the return being the important part because it allows you to chain the methods. In another post I mentioned that you can do a "before and after" type of test which might look like:
Helper.Tee(Helper.Tee(" _ before after _ ", Console.WriteLine)
.ToUpper().Trim()
.Substring(8,6),
Console.WriteLine);
That results in an output like the following:
_ before after _
AFTER
|
|
|
|
|
this example is relatively convoluted and pointless.
you find better and common use of functional programming in LINQ to Object!
|
|
|
|
|
Yes, it does look that way...and I'm learning this stuff myself.
However, I've provided a slightly better example in reply to Sander at:
The Weird and The Wonderful[^]
That at least makes a bit of sense.
|
|
|
|