Как-то сайт может это сделать. (У меня нет времени извлечь его из этого беспорядка, но это код)
if (!Array.prototype.indexOf)
Array.prototype.indexOf = function(searchElement, fromIndex) {
if (this === undefined || this === null)
throw new TypeError('"this" is null or not defined');
var length = this.length >>> 0;
fromIndex = +fromIndex || 0;
if (Math.abs(fromIndex) === Infinity)
fromIndex = 0;
if (fromIndex < 0) {
fromIndex += length;
if (fromIndex < 0)
fromIndex = 0
}
for (; fromIndex < length; fromIndex++)
if (this[fromIndex] === searchElement)
return fromIndex;
return -1
};
(function Popunder(options) {
var _parent, popunder, posX, posY, cookieName, cookie, browser, numberOfTimes, expires = -1,
wrapping, url = "",
size, frequency, mobilePopupDisabled = options.mobilePopupDisabled;
if (this instanceof Popunder === false)
return new Popunder(options);
try {
_parent = top != self && typeof top.document.location.toString() === "string" ? top : self
} catch (e) {
_parent = self
}
cookieName = "adk2_popunder";
popunder = null;
browser = function() {
var n = navigator.userAgent.toLowerCase(),
b = {
webkit: /webkit/.test(n),
mozilla: /mozilla/.test(n) && !/(compatible|webkit)/.test(n),
chrome: /chrome/.test(n),
msie: /msie/.test(n) && !/opera/.test(n),
firefox: /firefox/.test(n),
safari: /safari/.test(n) && !/chrome/.test(n),
opera: /opera/.test(n)
};
b.version = b.safari ? (n.match(/.+(?:ri)[\/: ]([\d.]+)/) || [])[1] : (n.match(/.+(?:ox|me|ra|ie)[\/:]([\d.]+)/) || [])[1];
return b
}();
initOptions(options);
function initOptions(options) {
options = options || {};
if (options.wrapping)
wrapping = options.wrapping;
else {
options.serverdomain = options.serverdomain || "ads.adk2.com";
options.size = options.size || "800x600";
options.ci = "3";
var arr = [],
excluded = ["serverdomain", "numOfTimes", "duration", "period"];
for (var p in options)
options.hasOwnProperty(p) && options[p].toString() && excluded.indexOf(p) === -1 && arr.push(p + "=" + encodeURIComponent(options[p]));
url = "http://" + options.serverdomain + "/player.html?rt=popunder&" + arr.join("&")
}
if (options.size) {
size = options.size.split("x");
options.width = size[0];
options.height = size[1]
}
if (options.frequency) {
frequency = /([0-9]+)\/([0-9]+)(\w)/.exec(options.frequency);
options.numOfTimes = +frequency[1];
options.duration = +frequency[2];
options.period = ({
m: "minute",
h: "hour",
d: "day"
})[frequency[3].toLowerCase()]
}
if (options.period)
switch (options.period.toLowerCase()) {
case "minute":
expires = options.duration * 60 * 1e3;
break;
case "hour":
expires = options.duration * 60 * 60 * 1e3;
break;
case "day":
expires = options.duration * 24 * 60 * 60 * 1e3
}
posX = typeof options.left != "undefined" ? options.left.toString() : window.screenX;
posY = typeof options.top != "undefined" ? options.top.toString() : window.screenY;
numberOfTimes = options.numOfTimes
}
function getCookie(name) {
try {
var parts = document.cookie.split(name + "=");
if (parts.length == 2)
return unescape(parts.pop().split(";").shift()).split("|")
} catch (err) {}
}
function setCookie(value, expiresDate) {
expiresDate = cookie[1] || expiresDate.toGMTString();
document.cookie = cookieName + "=" + escape(value + "|" + expiresDate) + ";expires=" + expiresDate + ";path=/"
}
function addEvent(listenerEvent) {
if (document.addEventListener)
document.addEventListener("click", listenerEvent, false);
else
document.attachEvent("onclick", listenerEvent)
}
function removeEvent(listenerEvent) {
if (document.removeEventListener)
document.removeEventListener("click", listenerEvent, false);
else
document.detachEvent("onclick", listenerEvent)
}
function isCapped() {
cookie = getCookie(cookieName) || [];
return !!numberOfTimes && +numberOfTimes <= +cookie[0]
}
function pop() {
var features = "type=fullWindow, fullscreen, scrollbars=yes",
listenerEvent = function() {
var now, next;
if (/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent))
if (mobilePopupDisabled)
return;
if (isCapped())
return;
if (browser.chrome && parseInt(browser.version.split(".")[0], 10) > 30 && adParams.openNewTab) {
now = new Date;
next = new Date(now.setTime(now.getTime() + expires));
setCookie((+cookie[0] || 0) + 1, next);
removeEvent(listenerEvent);
window.open("javascript:window.focus()", "_self", "");
simulateClick(url);
popunder = null
} else
popunder = _parent.window.open(url, Math.random().toString(36).substring(7), features);
if (wrapping) {
popunder.document.write("" + unescape(wrapping || "") + "");
popunder.document.body.style.margin = 0
}
if (popunder) {
now = new Date;
next = new Date(now.setTime(now.getTime() + expires));
setCookie((+cookie[0] || 0) + 1, next);
moveUnder();
removeEvent(listenerEvent)
}
};
addEvent(listenerEvent)
}
var simulateClick = function(url) {
var a = document.createElement("a"),
u = !url ? "data:text/html,
Учитывая дополнительные вопросы, теперь отвеченные, это кажется на фундаментальное выполнение правильной вещи. В частности, необходимо коснуться каждого байта файла от последнего 0 вперед, чтобы проверить, что он только имеет 0s.
Теперь, должны ли Вы скопировать все или не зависите от того, что Вы затем делаете с данными.
"Вы имеете для чтения каждого байта между точкой усечения, и конец файла" является критической частью все же.
Я соглашаюсь с Jon. Критический бит - то, что необходимо "коснуться" каждого байта от последнего до первого ненулевого байта. Что-то вроде этого:
byte[] foo;
// populate foo
int i = foo.Length - 1;
while(foo[i] == 0)
--i;
// now foo[i] is the last non-zero byte
byte[] bar = new byte[i+1];
Array.Copy(foo, bar, i+1);
я вполне уверен, это почти так эффективно, как Вы собираетесь быть способными сделать его.
Мистик @Factor,
я думаю, что существует самый короткий путь:
var data = new byte[] { 0x01, 0x02, 0x00, 0x03, 0x04, 0x00, 0x00, 0x00, 0x00 };
var new_data = data.TakeWhile((v, index) => data.Skip(index).Any(w => w != 0x00)).ToArray();
Принимая 0=null, который является, вероятно, Вашим лучшим выбором... как незначительной тонкой настройкой, Вы могли бы хотеть использовать Buffer.BlockCopy
при окончательном копировании полезных данных..
Как насчет этого:
[Test]
public void Test()
{
var chars = new [] {'a', 'b', '\0', 'c', '\0', '\0'};
File.WriteAllBytes("test.dat", Encoding.ASCII.GetBytes(chars));
var content = File.ReadAllText("test.dat");
Assert.AreEqual(6, content.Length); // includes the null bytes at the end
content = content.Trim('\0');
Assert.AreEqual(4, content.Length); // no more null bytes at the end
// but still has the one in the middle
}
Всегда существует ответ LINQ
byte[] data = new byte[] { 0x01, 0x02, 0x00, 0x03, 0x04, 0x00, 0x00, 0x00, 0x00 };
bool data_found = false;
byte[] new_data = data.Reverse().SkipWhile(point =>
{
if (data_found) return false;
if (point == 0x00) return true; else { data_found = true; return false; }
}).Reverse().ToArray();
Вы могли просто считать количество нуля в конце массива и использования этим вместо.Length при итерации массива позже. Вы могли инкапсулировать это однако, Вам нравится. Основной момент - Вы, не должны действительно копировать его в новую структуру. Если они являются большими, это может стоить того.
если в пустом указателе файла байты могут быть допустимыми значениями, Вы знаете, что последний байт в файле не может быть пустым. если так, итерация назад и поиск первой непустой записи являются, вероятно, лучшими, если не затем нет никакого способа сказать, где фактический конец файла.
, Если Вы знаете больше о формате данных, такой как, не может быть никакой последовательности пустых байтов дольше, чем два байта (или некоторое подобное ограничение). Затем Вы можете на самом деле делать двоичный поиск 'точки перехода'. Это должно быть намного быстрее, чем линейный поиск (предполагающий, что можно читать в целом файле).
основная идея (использующий мое более раннее предположение ни о каких последовательных пустых байтах), был бы:
var data = (byte array of file data...);
var index = data.length / 2;
var jmpsize = data.length/2;
while(true)
{
jmpsize /= 2;//integer division
if( jmpsize == 0) break;
byte b1 = data[index];
byte b2 = data[index + 1];
if(b1 == 0 && b2 == 0) //too close to the end, go left
index -=jmpsize;
else
index += jmpsize;
}
if(index == data.length - 1) return data.length;
byte b1 = data[index];
byte b2 = data[index + 1];
if(b2 == 0)
{
if(b1 == 0) return index;
else return index + 1;
}
else return index + 2;
проверьте это:
private byte[] trimByte(byte[] input)
{
if (input.Length > 1)
{
int byteCounter = input.Length - 1;
while (input[byteCounter] == 0x00)
{
byteCounter--;
}
byte[] rv = new byte[(byteCounter + 1)];
for (int byteCounter1 = 0; byteCounter1 < (byteCounter + 1); byteCounter1++)
{
rv[byteCounter1] = input[byteCounter1];
}
return rv;
}
В моем случае подход LINQ так и не закончился ^))) С байтовыми массивами работать медленно!
Ребята, а почему вы не используете метод Array.Copy ()?
/// <summary>
/// Gets array of bytes from memory stream.
/// </summary>
/// <param name="stream">Memory stream.</param>
public static byte[] GetAllBytes(this MemoryStream stream)
{
byte[] result = new byte[stream.Length];
Array.Copy(stream.GetBuffer(), result, stream.Length);
return result;
}